0

これが私がやりたいことです:

  1. メイン スレッド (UI を制御するスレッド) にワーカー スレッドを作成します。
  2. ワーカー スレッドは、メイン スレッドによってシャットダウンされるまで実行を続けます (これは、アプリケーション全体がシャットダウンされた場合にのみ発生します)。
  3. メイン スレッドはキーアップをリッスンしますが、ワーカー スレッドにイベントを送信してキーアップを非同期的に処理します (UI のブロックを回避するため)。
  4. キーアップが処理されると、ワーカー スレッドが UI を更新します。

これまでのところ、キーアップがあるたびに新しいスレッドを作成してきましたが、この方法ではオーバーヘッドが多すぎるようです。

私が知る限り、BackgroundWorker クラスを使用する必要がありますが、私が見た例では、バックグラウンド ワーカーを開始し、メイン スレッドでブロックされていない UI を続行し、完了したら BackgroundWorker から UI を更新するようです。私がすでにやっているのと同じです。

実行する作業がないときにワーカースレッドが実行され続けてスリープするようにするにはどうすればよいですか?

4

3 に答える 3

1

Zachesの回答は完全に有効ですが(そして私がしばらく使用したアプローチです)、次を使用したよりエレガントなソリューションだと思うものに出くわしましたDispatcher

ワーカー スレッドを作成します。

Dispatcher _workerDispatcher;
Thread _workerThread = new Thread(new ThreadStart(() =>
{
    _workerDispatcher = Dispatcher.CurrentDispatcher; // Required to create the dispatcher
    Dispatcher.Run(); // Keeps thread alive and creates a queue for work
});
_workerThread.Start();

(メイン スレッドまたは別のスレッドから) ワーカー スレッドに作業を入れます。

// Synchronous work
_workerDispatcher.Invoke(() =>
{
    // Do stuff
});

// Asynchronous work (makes most sense for background work)
_workerDispatcher.BeginInvoke(() =>
{
    // Do stuff
});

ワーカー スレッドをシャットダウンします。

_workerDispatcher.InvokeShutdown();
_workerThread.Join(); // Wait for thread to shut down

アパートメントの状態を設定する必要があるので使用していますが、 と を使用しnew Thread()て作成したタスクを使用することもできます。Task.Run()Task.Factory.StartNew()

を呼び出す必要があることを 100% 確信しているわけではありませんthread.Join()が、スレッドがシャットダウンされていることは確かです。代わりにTask通話を使用している場合。task.Wait()

を取得するもう 1 つの方法Dispatcherは を呼び出すことですが、(後で参照を使用しない場合でも) が使用されるまでは作成されないことDispatcher.FromThread(thread)に注意することが重要です。DispatcherCurrentDispatcher

このアプローチの欠点は、複数のスレッドがキューからアイテムを選択して動作させるために使用できないことです。そのためには、Zaches の回答で説明されているプロデューサー/コンシューマー アプローチを使用する必要があります。ディスパッチャー アプローチを使用すると、特定の広告で作業をキューに入れることができます。

于 2015-08-06T11:24:24.503 に答える
0

あなたが抱えている問題は生産者/消費者問題と呼ばれています。そして、利用可能な ConcurrentCollections のいずれかを使用して簡単に解決できます。

次のようなことを試してください:

var queue = new ConcurrentQueue<string>();
var consume = true;

var producer = Task.Run(() => 
{
    var input = Console.ReadLine();
    while(!string.IsNullOrEmpty(input) 
    {
       queue.Enqueue(input);
       input = Console.ReadLine();         
    }
});

var consumer = Task.Run(() => 
{
    while(consume) //So we can stop the consumer
    {
        while(!queue.IsEmpty) //So we empty the queue before stopping
        {
            stringres;
            if(queue.TryDequeue(out res)) Console.WriteLine(res);
        }
    }
});

await producer;
consume = false;
await consumer;

スレッドを手動で開始する代わりに、タスク パターン ライブラリを使用してみてください。それはあなたの友達です。

于 2013-10-03T09:48:20.197 に答える
0

Task Parallel Libraryを使用してみませんか?

KeyUp イベントを検出するたびに新しいタスクを作成し、TPL に新しいスレッドの作成を心配させます。スレッド プールを使用するため、イベントが発生するたびに新しいスレッドが作成されるわけではありません。

于 2013-10-03T09:18:24.373 に答える