前回の非同期処理では、別スレッドからUIコントロールの Label1.Text 更新が出来ませんでしたので、別スレッドからUIコントロール更新の仕方を浚ってみる事に。
別スレッドで実行しているメソッドがUIを書き換える場合、処理をUIスレッドに移行する必要が有りますが、それにはWindowsフォームが備えているInvokeメソッドを呼び出すと良い様です。
尚、別スレッドで実行されると分かっているなら、直接Invokeメソッドを呼び出した方が簡単なのですが、後の改修などを考慮してInvokeRequiredプロパティを使用するのが定石?なんだそうです。
<注意点>
・InvokeRequiredプロパティは、UIスレッドと異なるスレッドで実行していると"真"を返します。
・分かり易い?様に敢えて、別スレッドからUIを更新する為のデリゲートを定義していますが、(関数呼び出しとは違い)デリゲートの名称は区別されず、同一のシグネチャが重要なので、「Invoke(New dlgtShowMsg(AddressOf SetLabel1Text), ・・・)」でも構いません。
お試し環境
Windows7 64bit Edition
Visual Basic 2008 AnyCPU対象
/*-------------------------------- お試し結果 ------------------------------*/
・メッセージボックスの表示は、前回と同じなので省略
・ボタン3を押すと、約2秒後にラベルのテキストを表示
/*----------------------------------------------------------------------------*/
/*---------------------------- お試しソース -------------------------------*/
Public Class Form3
Delegate Sub dlgtShowMsg(ByVal msg As String)
Private Sub ShowMessage(ByVal msg As String) ' BeginInvokeから呼ばれるので別スレッド
System.Threading.Thread.Sleep(2000)
Invoke(New dlgtSetLabel1(AddressOf SetLabel1Text), "Asynchronous Method" & " and " & msg) ' 別スレッドからUIを更新するInvoke呼出し
MsgBox(msg, MsgBoxStyle.Information, "Asynchronous Method")
End Sub
Private Sub showCallback(ByVal ar As IAsyncResult) ' コールバックメソッド
Dim arShowMsg As dlgtShowMsg
arShowMsg = CType(ar.AsyncState, dlgtShowMsg)
arShowMsg.EndInvoke(ar)
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim showMsg As dlgtShowMsg
Dim ar As IAsyncResult
showMsg = New dlgtShowMsg(AddressOf ShowMessage)
ar = showMsg.BeginInvoke("See actions", New AsyncCallback(AddressOf showCallback), showMsg)
MsgBox("See actions", MsgBoxStyle.Information, "Asynchronous Test")
End Sub
Delegate Sub dlgtSetLabel1(ByVal msg As String) ' ①別スレッドからUIを更新するデリゲートの定義
Private Sub SetLabel1Text(ByVal msg As String) ' ②別スレッドからUIを更新するメソッドの作成
If InvokeRequired = True Then ' ③Windowsフォームは別スレッドからのUI操作は保障されていない
Invoke(New dlgtSetLabel1(AddressOf SetLabel1Text), "Required " & msg)
Else
Label1.Text = msg
End If
End Sub
End Class
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*============================================================================*/