たとえばワーカースレッドを作って、ワーカースレッド上で重い処理を走らせ、その結果をコントロールに表示させようとします。
Private Sub Button1_Click(... Dim t = New Threading.Thread(AddressOf worker1) t.Start() End Sub Sub worker1() ' 重い処理(略) ' 重い処理の結果を書く Button1.Text = Now.ToString ' エラーになる End Sub
ところが、これはエラーになります。コントロールへのアクセスは UI スレッドからしかアクセスできないためです。
System.InvalidOperationException が発生しました。 有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'Button1' がアクセスされました。
これを回避するためには、ワーカースレッドから UI スレッドに処理をお願い(Invoke)する必要があります。
ところが、この UI スレッドにお願いする方法が、使用するアプリケーションプラットホームによって書き方が異なります。
以下列挙。
- Windwos Forms の場合
Me.BeginInvoke、または Me.Invoke を使用します。
Control クラスのメソッドのようなので、Button.Invoke でも可能ですが、Me(=Form)でいいと思います。Sub worker1() Me.BeginInvoke( _ Sub() Button1.Text = Date.Now.ToString End Sub) End Sub
- WPF の場合
Application.Current.Dispatcher.BeginInvoke、または Application.Current.Dispatcher.Invoke を使用します。
Sub worker1() Application.Current.Dispatcher.BeginInvoke( _ Sub() Button1.Content = Date.Now.ToString End Sub) End Sub
- Windows Phone(Silverlight系)の場合
Deployment.Current.Dispatcher.BeginInvoke を使います。 Silverlight 系は Invoke はないみたいですね。
Sub worker1() Deployment.Current.Dispatcher.BeginInvoke( _ Sub() Button1.Content = Date.Now.ToString End Sub) End Sub
- WinRT(ストアアプリ系)の場合
Me.Dispatcher.RunAsync を使います。
"Dim dummy =" はコンパイラーの警告回避用です(汗Sub worker1() Dim dummy = Me.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, _ Sub() Button1.Content = Date.Now.ToString End Sub) End Sub
Invoke 相当の動作にするためには、"Dim dummy =" の部分を "Await" に変えるか、次の行に "Await dummy" を追加して待たせます。
以下は "Await dummy" を追加してみた例。(Sub のところの Async も忘れずに)Async Sub worker1() Dim dummy = Me.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, _ Sub() Button1.Content = Date.Now.ToString End Sub) Await dummy End Sub
また、ストアアプリではワーカースレッドの生成に Threading.Thread が使えないので、Threading.Tasks.Task で生成しています。
Private Sub Button1_Click(... Dim t = New Threading.Tasks.Task(AddressOf worker1) t.Start() End Sub
[VB.NET] ワーカースレッドから コントロール(UI スレッド)へのアクセス その2 | オールトの雲
[...] [VB.NET] ワーカースレッドから コントロール(UI スレッド)へのアクセス その1 [...]
Link | 2013年8月29日 21:18