- PR -

別スレッドで発生した例外の捕捉について

1
投稿者投稿内容
未記入
常連さん
会議室デビュー日: 2007/05/01
投稿数: 35
投稿日時: 2007-06-28 16:12
お世話になっております。

VB.NETでソケット通信プログラムを作成しております。
クライアント⇒サーバの接続確立時に、それを監視するための
スレッドを生成し、一定時間経過した場合にExceptionをスローする。
という処理を取り入れようとしています。

ここで、別スレッドでExceptionをスローした場合、
その例外をスレッド呼び出し元で捕捉できずに困っております。
どなたか解決方法を教えていただけないでしょうか?

現在のコードは下記のような状態です。

'接続監視用スレッド
Private Sub WatchConnect()
System.Threading.Thread.Sleep(My.Settings.Timeout)
Throw New TimeOutException("通信タイムアウトのため例外を発生させます")
End Sub

'サーバとの通信を開始
Friend Sub StartCommunicate()
logger.Debug("start:StartCommunicate")

'サーバーのホスト名とポート番号
Dim host As String = My.Settings.hostIPAddress
Dim port As Integer = My.Settings.port
Dim RETRY_CNT As Integer = My.Settings.retryCount
Dim retryCnt As Integer = 0

While True
'接続監視用に別スレッドを生成し、サーバとの接続処理を監視する
Dim watchThread As New Thread(New ThreadStart(AddressOf WatchConnect))
Try

watchThread.Start()
'TcpClientを作成し、サーバーと接続する
Dim client As New TcpClient(host, port)
'NetworkStreamを取得する
networkStream = client.GetStream()
binaryWriter = New BinaryWriter(networkStream)
binaryReader = New BinaryReader(networkStream)
Exit While
Catch ex As TimeOutException
logger.Error(ex)
If retryCnt = RETRY_CNT Then
Throw ex
End If
retryCnt = retryCnt + 1
client = Nothing
Catch ex As Exception
logger.Error(ex)
If retryCnt = RETRY_CNT Then
Throw ex
End If
retryCnt = retryCnt + 1
client = Nothing
System.Threading.Thread.Sleep(My.Settings.retryInterval)
Finally
watchThread.Abort()
End Try

End While

logger.Debug("end:StartCommunicate")
End Sub

以上、よろしくお願いいたします。
未記入
常連さん
会議室デビュー日: 2007/05/01
投稿数: 35
投稿日時: 2007-06-28 16:18
すいません。コードのインデントが設定されていないので、
非常にみにくいですね。もう一度書き込みさせてください。

'接続監視用スレッド
Private Sub WatchConnect()
System.Threading.Thread.Sleep(My.Settings.Timeout)
Throw New TimeOutException("通信タイムアウトのため例外を発生させます")
End Sub

'サーバとの通信を開始
Friend Sub StartCommunicate()
logger.Debug("start:StartCommunicate")

'サーバーのホスト名とポート番号
Dim host As String = My.Settings.hostIPAddress
Dim port As Integer = My.Settings.port
Dim RETRY_CNT As Integer = My.Settings.retryCount
Dim retryCnt As Integer = 0

While True
'接続監視用に別スレッドを生成し、サーバとの接続処理を監視する
Dim watchThread As New Thread(New ThreadStart(AddressOf WatchConnect))

Try
watchThread.Start()
'TcpClientを作成し、サーバーと接続する
Dim client As New TcpClient(host, port)
'NetworkStreamを取得する
networkStream = client.GetStream()
binaryWriter = New BinaryWriter(networkStream)
binaryReader = New BinaryReader(networkStream)
Exit While
Catch ex As TimeOutException
logger.Error(ex)
If retryCnt = RETRY_CNT Then
Throw ex
End If
retryCnt = retryCnt + 1
client = Nothing
Catch ex As Exception
logger.Error(ex)
If retryCnt = RETRY_CNT Then
Throw ex
End If
retryCnt = retryCnt + 1
client = Nothing
System.Threading.Thread.Sleep(My.Settings.retryInterval)

Finally
watchThread.Abort()
End Try
End While

logger.Debug("end:StartCommunicate")
End Sub


ぽぴ王子
ぬし
会議室デビュー日: 2006/03/24
投稿数: 475
お住まい・勤務地: お住まい:城・勤務地:城
投稿日時: 2007-06-28 16:31
コードを入力するときは、BBコードを使うといいです。

[code]
[/code]
というようなタグで囲むとインデントも正しくやってくれますよ(これは全角で
書いてますが、実際は半角で入力します)。

で、別スレッドで発生した Exception ですが、基本的には取れないと思
います。
別スレッドで発生した Exception を自スレッドで取得することは不可能だ
と思うので、やるとしたら別スレッド内でキャッチした Exception を
Invoke で渡してもらう(受け取った Exception を Exception 型のオブ
ジェクトとして扱う)とか、Application.ThreadException イベントを定
義してキャッチするような感じになると思います。
_________________
ぽぴ王子@わんくま同盟
ぽぴ王子の人生プログラミング中 / ぽぴンち。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-06-28 20:34
ごめんなさい、コードからしたいことが読み取れませんでした。

WatchConnect は、不要だと思います。Timmer で十分ではないでしょうか。

いや、スレッドをわける必要があるとお考えの場合、あなたが考えている処理を、日本語で説明してください。

今の実装では、指定時間後に例外が発生するというだけです。タイマーでイベントを発生させ、フラグを立てれば十分だと思います。
_________________
未記入
常連さん
会議室デビュー日: 2007/05/01
投稿数: 35
投稿日時: 2007-06-28 20:38
Jittaさん、回答ありがとうございます。

>WatchConnect は、不要だと思います。Timmer で十分ではないでしょうか。
>いや、スレッドをわける必要があるとお考えの場合、あなたが考えている処理を、日>本語で説明してください。
>今の実装では、指定時間後に例外が発生するというだけです。タイマーでイベントを>発生させ、フラグを立てれば十分だと思います。
申し訳ありません。別スレッドからの例外をメインスレッドで捕捉できると
思い込んでいました。。。
タイマーを用いた接続監視方法の
具体的なコーディング例を教えていただけないでしょうか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-06-29 07:45
具体的なコードは、MSDNに例示されていると思いますが、探してみましたか?探す手間くらいは、惜しまずかけて欲しいです。
それで見つからなければ、どの検索エンジンで、どの様なキーワードで検索したか、教えてください。
また、仕様が分からなければ、コードを書くことも難しいです。


今携帯からなので、コード例をあげるとなると、夜まで待っていただくことになります。それより、自分で探す方が早いと思いますよ。
ugaya
会議室デビュー日: 2006/08/03
投稿数: 18
投稿日時: 2008-03-01 17:47
見たところASP.NETでの実装ではなさそうなので、どうしても別スレッドの例外を補足するような事がしたい場合はBackGroundWorkerを使えばよいと思います。
.net2.0以上限定になりますが。
BackGroundWorkerでは、RunWorkerCompletedイベントがメインスレッドで発生します。

ですので
DoWorkイベントのイベントハンドラで監視メソッドをループさせます。
例外を投げたい状態に移行したら、ループを終了させRunWorkerCompletedイベントのイベントハンドラで例外を投げます。

厳密には別スレッドの例外の補足ではないですが、同じようなことが実現できると思います。

未熟なので少し恥ずかしいですが、自サイトにサンプルコードをC#でおいておきました。
よければ読んで見てください。
1

スキルアップ/キャリアアップ(JOB@IT)