2011-12-15 34 views
3

私はwpfを使用しています。私のUIにボタンがあります。新しいスレッドのDispatcher.InvokeがUIをロックしています

ユーザがクリックすると、autoreseteventを使って新しいスレッドで新しいメソッドを実行するforループがあります。

その新しいスレッドでは、私はラベルを使用しています、それをlblStatusと呼ぶことにしましょう。私はあなたのUIにないこのスレッドでそのラベルを更新したいと思います。 wpfを使用して、私はDispatcher.Invokeを使用する必要があります。

Thread thread= new Thread(StartLooking); 
thread.Start(); 
_waitHandle.WaitOne(); 

private void StartLooking(object value) 
{ 
if (lblStatus.Dispatcher.Thread == Thread.CurrentThread) 
     { 
      lblStatus.Content = "Scanning>..."; 
     } 
     else 
     { 
      lblStatus.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => lblStatus.Content = "Scanning>>>>>")); 
     } 
_waitHandle.Set(); 
} 

プログラムはちょうどここに停止します

はここに私のコードのサンプルです。それはラベルの内容を変更しません、それは私のUIに戻りますが、それをブロックします。
私も

lblStatus.Dispatcher.Invoke(DispatcherPriority.Normal, new LblStatusThreadCheck(lblStatusThreadCheck), "Scanning..."); 

を試してみたが、それも機能していません。何か案は?

+1

データバインディングを使用することを考えましたか? – GETah

+0

何かをする前に新しいスレッドを開始して操作を完了するのを待つのはなぜですか? – whoisthis

答えて

5

問題は、あなたがInvokeを使用しているので、これを実行できないということです。

UIスレッドが処理するまで、Dispatcher.Invokeは返されません。ただし、_waitHandle.WaitOne();を呼び出してUIスレッドをブロックし、この処理が完了するまで待機ハンドルを設定しないでください。この2つは効果的にデッドロックを引き起こします。

代わりにBeginInvokeを使用するように切り替えると、UIが要素をキューに入れ、待機ハンドルが設定されます。次にラベルが更新されます。しかし、それは機能し、ブロックされません。

0

おそらくBeginInvokeを使用します。 Invokeは、UIスレッドがアクションを実行し、優先度をバックグラウンドに設定しているので、これを呼び出すスレッドをブロックします。これには時間がかかることがあります。

2

前の2件の記事が既にあなたのコード内の問題、ちょうど提案をカバーしているので:

if (lblStatus.Dispatcher.Thread == Thread.CurrentThread) 

代わりの

if (!lblStatus.CheckAccess()) 

それはきれいだし、あなたが望む正確な意図を持って使用してみてください。ただそれについて読むのはhereです。

関連する問題