私のコードには現在、次の 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 番目のオプションは、従来のワーカー スレッド パターンを置き換える正しい方法ですか?