- ベストアンサー
マルチスレッド[ VB.NET 2005 ]で通信DLLを呼び出す方法
- VB.NET 2005で作成したプログラムで、マルチスレッドを使用して通信DLLを呼び出す方法についてご質問です。
- 具体的には、スレッドスタート時に別スレッドで動作するfSockInit関数と、メインスレッドで動作するfConnect関数、fParmSet関数の違いについて説明してください。
- また、frmMain_Loadで作成したスレッドを指定して関数を呼び出す方法についても教えてください。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
稼働中の別スレッドにメインスレッドから特定の関数を呼び出させるには、別スレッド側でメインスレッドからの要求を受け入れる仕組みが必要になります。 作り方はいろいろあると思いますが、下記のようなマルチスレッドモデルを作ってみたので参考にしてみてください。 別スレッドがメインスレッドの要求を待機する手段にManualResetEventを使っています。 また、呼び出すメソッドを動的に変更できるようにデリゲートを使っています。 スレッドセーフに関する対処は一切していません。 Public Class Form2 ' 別スレッドから呼び出させるメソッドのデリゲート Private dgtMethod As SampleMethodHandler = Nothing ' 別スレッドから呼び出すメソッドのデリゲート宣言 Private Delegate Sub SampleMethodHandler(ByVal Message As String) ' 別スレッドの実行を制御するためのイベント Private mWait() As System.Threading.ManualResetEvent Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load ' 別スレッドの分だけイベントを作る Array.Resize(mWait, 2) ' ThreadWorkメソッドを2つの別スレッドで動かす For i As Integer = 0 To 1 mWait(i) = New Threading.ManualResetEvent(False) Dim thrdNew As New Threading.Thread(AddressOf ThreadWork) thrdNew.Start(mWait(i)) Next End Sub Private Sub Form2_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed ' 別スレッドを終了させる dgtMethod = Nothing mWait(0).Set() mWait(1).Set() End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click ' 別スレッド1からSampleMethodをコールする dgtMethod = New SampleMethodHandler(AddressOf SampleMethod) mWait(0).Set() End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click ' 別スレッド2からSampleMethodをコールする dgtMethod = New SampleMethodHandler(AddressOf SampleMethod) mWait(1).Set() End Sub ' 別スレッドで動かすメソッド Private Sub ThreadWork(ByVal ResetEvent As Object) Dim evtWait As Threading.ManualResetEvent evtWait = CType(ResetEvent, Threading.ManualResetEvent) Console.WriteLine("別スレッド開始") Do ' イベントの呼び出しがあるまで待機 evtWait.WaitOne() ' イベントをリセットし、次回のWaitOne()で停止 evtWait.Reset() ' デリゲートが指定されていなければループ脱出 If dgtMethod Is Nothing Then Exit Do ' 指定されたデリゲートを呼び出す dgtMethod.Invoke("Invokeによる呼び出し") dgtMethod = Nothing Loop Console.WriteLine("別スレッド終了") End Sub Private Sub SampleMethod(ByVal Message As String) Console.WriteLine(Message & ":ThreadID = " & Threading.Thread.CurrentThread.ManagedThreadId.ToString) End Sub End Class 私自身、マルチスレッドの経験は少ないのでもっとスマートな方法があるかもしれませんが・・・。
その他の回答 (1)
- うぃず(@Wizard_Zero)
- ベストアンサー率69% (344/495)
フィールドに Private strArg As String として変数を用意し、イベントをSetする前に文字列を設定。 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click ' 別スレッド1からSampleMethodをコールする dgtMethod = New SampleMethodHandler(AddressOf SampleMethod) strArg = "表示するメッセージ" mWait(0).Set() End Sub 別スレッドからのInvokeで変数を指定。 dgtMethod.Invoke(strArg) という手続きにすればよいかと。 ただこのままの方法だと、スレッドが複数あるのにフィールド変数がひとつだけである点が不恰好ですかね・・・。呼び出すメソッドの引数が数や型が異なった場合にどうするか、という対応も必要になります。
お礼
その方法しかないですかね~。。。 いろいろ試してみます。とても参考になりました。 ありがとうございました。
お礼
ご回答頂き、ありがとうございます。 問題解決に一歩前進しました。 上記のサンプルソースについて質問なのですが() > dgtMethod.Invoke("Invokeによる呼び出し") →"Invokeによる呼び出し"を任意の値にしたい場合、 どうすればいいのでしょうか? 宜しくお願い致します。