3

メッセージ/リクエストを受信して​​非同期で実行する Windows サービスを作成しています。アイテムが完了するのを待つ必要も、結果を気にする必要もありません。System.Threading.Tasks.Task を使用して、リクエストをタスクとして正常に実行できます。これらの項目のほとんどはすぐに実行されます (1 秒未満) が、一部の項目はより長く (2 ~ 3 分) かかります。

Windows サービスとして、「停止」コマンドに応答する必要があり、一部のタスクは引き続き実行されます。実行時間が長いタスクはデータを悪い状態のままにする可能性があるため、タスクをキャンセルしないことをお勧めします (ロールバックは非常にトリッキーです)。

これを処理する最善の方法は何ですか? WaitAll を実行できるように、開始したタスクのリストを保持することを考えました。サービスの実行中、何万ものリクエストが処理されます。リストが大きくならないように、完了したタスクをリストから削除するタイミングをどのように知ることができますか? それほど多くの Task オブジェクトへの参照を保持する必要はないと思います。

前もって感謝します。

4

2 に答える 2

1

CancellationTokenこの目的に使用できます。OnStopイベントが発生したら、でメソッドCancel()を呼び出すだけCancellationTokenSourceで、トークンを渡したすべてのタスクに伝播されます。タスクを正しくキャンセルする方法はいくつかあります。キャンセルが要求された場合は、タスク内で時々明示的に確認できます。または、トークン自体にプロパティThrowWhenCancelledがあり、キャンセルが要求された場合、トークンは。をスローすると思いますCancellationException

タスクの結果は気にしないが、追跡リストが必要なList<Task<T>>場合は、(またはConcurrentBag<Task<T>>)をローカル変数として保持するだけです。時々、リストを調べてTask.Statusプロパティが実行されているかどうかを確認する別のタスクを開始します。

それらの参照を正しく維持している限り、多くの参照を維持することが問題になるとは思いません。また、アプリケーションをどのように停止するかによっても異なります。アプリケーションと一緒にタスクが強制終了されても問題がない場合は、それらを追跡できない可能性があります(保持するリソースがいくつかあり、解放する必要がある場合を除く)。しかし、ほとんどの場合、正しくファイナライズする必要があります。

編集:投稿を読み直してください。RequestAdditionalTime呼び出しは、長時間実行されるタスクが終了するまで待つのに役立つ場合があります。MSDNで確認してください:ServiceBase.RequestAdditionalTimeメソッド

于 2012-08-18T14:26:12.060 に答える
1

サービスが終了する前に終了するタスクのみを気にする場合は、Threadの代わりに を使用することをお勧めしTaskます。

new Thread(WorkerMethod).Start();

この方法で作成されたスレッドはいわゆるフォアグラウンド スレッドであり、アプリケーション (サービス) はすべてのフォアグラウンド スレッドが終了するまで終了しません。すべてのフォアグラウンド スレッドがどのような条件下でもハングしないようにする必要があります。そうしないと、アプリケーションが勝手に終了することはありません。で同じことを達成できTaskますが、実行したすべてのタスクのリストを保持Task.WaitAllし、Stop イベントですべてのタスクが終了するまで待機する必要があります。

スレッドを制御する (つまりスレッドへの参照を保持する) 必要がある場合は、何らかのコレクションを使用する必要があります。

List<Thread> threads = new List<Thread>();
Thread thrd;
threads.Add(thrd = new Thread(WorkerMethod));
thrd.Start();

ただし、実際にタスク/スレッドを制御およびキャンセルする必要がある場合はTask、キャンセルが容易になる方を使用する必要があります。

于 2012-08-20T12:46:51.283 に答える