3

私のコードには現在、次の 10 個のワーカー スレッドがあります。各ワーカー スレッドは、キューからジョブをポーリングし続け、実行時間の長いジョブを処理します。

for (int k=0; k<10; k++)
{
  Task.Factory.StartNew(() => DoPollingThenWork(), TaskCreationOptions.LongRunning);
}

void DoPollingThenWork()
{
  while (true)
  {
    var msg = Poll();
    if (msg != null)
    {
      Thread.Sleep(3000); // process the I/O bound job
    }
  }
}

async/await パターンを使用するように基になるコードをリファクタリングしています。上記のコードを次のように書き換えることができると思います。非同期タスクを作成し続ける 1 つのメイン スレッドを使用し、SemaphoreSlim を使用して同時実行タスクの数を 10 に抑制します。

Task.Factory.StartNew(() => WorkerMainAsync(), TaskCreationOptions.LongRunning);

async Task WorkerMainAsync()
{
  SemaphoreSlim ss = new SemaphoreSlim(10);
  while (true)
  {
    await ss.WaitAsync();
    Task.Run(async () => 
              {
                await DoPollingThenWorkAsync();
                ss.Release();
              });
  }
}

async Task DoPollingThenWorkAsync()
{
  var msg = Poll();
  if (msg != null)
  {
    await Task.Delay(3000); // process the I/O-bound job
  }
}

どちらも同じように動作する必要があります。しかし、スレッドをブロックしないため、2 番目のオプションの方が優れていると思います。しかし、欠点は、タスクが発射して忘れるようなものであるため、Wait (タスクを適切に停止する) を実行できないことです。2 番目のオプションは、従来のワーカー スレッド パターンを置き換える正しい方法ですか?

4

2 に答える 2