3

私は wpf を使用しています。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...");

も同様ですが、それも機能していません。何か案は?

4

4 に答える 4

7

問題は、Invoke を使用しているため、これを実行できなくしていることです。

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

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

于 2011-12-15T23:01:56.637 に答える
3

以前の 2 つの投稿で既にコードの問題がカバーされているため、単なる提案:

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

使ってみて

if (!lblStatus.CheckAccess())

それはよりクリーンで、あなたが望む正確な意図を持っています。ここでそれについて読んでください

于 2011-12-15T23:05:59.433 に答える
0

BeginInvokeおそらく代わりに使用したいでしょう。InvokeUIスレッドがアクションを実行するまで、それを呼び出したスレッドをブロックします。優先度をバックグラウンドに設定しているため、これには時間がかかる場合があります.

于 2011-12-15T22:58:21.967 に答える