4

複数のスレッドを開始していますが、いずれかがいつ終了するかを知りたいです。私は次のコードを知っています:

foreach (Thread t in threads)
    t.Join();

ただし、すべてのスレッドが一緒になるのを待つだけです。それは遅すぎる。他のスレッドがまだ実行中であっても、1 つのスレッドがいつ終了するかを知る必要があります。WaitAnyスレッドのみに相当するものを探しています。しかし、監視しているすべてのスレッドにコードを追加することはできないため、シグナルやその他の同期オブジェクトを使用することはできません。

明確化:私は、アプリケーションのアクティビティをログに記録するログ/トレース ツールに取り組んでいます。スレッドの開始時にログ ステートメントを挿入できますが、スレッドから出る可能性のあるすべての方法 (複数の終了ポイント、例外など) にログ ステートメントを挿入することはできません。そのため、新しいスレッドを登録して、ログ エントリの書き込みが終了したときに通知を受け取りたいと考えています。すべてのスレッドで非同期にできますJoinが、それは監視対象のスレッドごとに 2 番目のスレッドを意味し、オーバーヘッドが少し大きくなる可能性があります。BackgroundWorkerスレッドは、Taskやプール スレッドなど、さまざまな手段で使用されます。本質的に、それはスレッドであり、それがいつ完了するかを知りたい. 正確なスレッド メカニズムは、ロギング ソリューションではなく、アプリケーションによって定義されます。

4

5 に答える 5

5

Threads の代わりにTasksを使用します。メソッドWaitAnyがあります。

Task.WaitAny

ここで読めるように、

  • システム リソースのより効率的でスケーラブルな使用。
  • スレッドまたはワークアイテムよりもプログラムによる制御が可能です。
于 2013-08-25T08:56:43.577 に答える
1

私の答えは、あなたが持っているのはThread.Current. 免責事項:IMO、あなたがやろうとしていることはハックであるため、私の考えもハックです.

したがって、リフレクションを使用して、目的のスレッドのネイティブ Win32 ハンドルのセットを取得します。Thread.GetNativeHandleであるメソッドを探しているinternalので、 のように呼び出しますthread.GetType().InvokeMember("GetNativeHandle", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic, ...)。選択したリフレクション ツールまたはフレームワーク ソースを使用して、詳細を確認してください。ハンドルを取得したら、次のいずれかのオプションに進みます。

  • 独自の実装をセットアップしSynchronizationContext(そこから派生)、SynchronizationContext.WaitHelper(waitAll: false)を使用してアンマネージ ハンドルを待機します。

  • WaitForMultipleObjectsorのような未加工の Win32 API を使用しますCoWaitForMultipleObjects(メッセージを送り出す必要があるかどうかによって異なります)。

別の子スレッドまたはプール スレッドで待機を実行します。

[編集済み]ターゲット スレッドの実行環境によっては、マネージド スレッドとアンマネージド スレッド間の 1 対 1 のマッピングが保証されないため、このハックが機能しない場合があります。

マネージド スレッドのコードを実行している Windows スレッドを特定し、そのハンドルを取得することができます。ただし、マネージ スケジューラは別の Windows スレッドでマネージ スレッドの実行を継続できるため、この Windows スレッドに対して SetThreadAffinityMask 関数を呼び出すことには意味がありません。

ただし、これはカスタム CLR ホストのみを意味する可能性があります。また、とでマネージ スレッド アフィニティを制御できるようです。Thread.BeginThreadAffinityThread.EndThreadAffinity

于 2013-08-25T11:04:44.647 に答える
1

私の意見WaitHandle.WaitAnyでは、いくつかの xyz の理由でそれを使用したくないので、このようなことを試すことができるため、最良の解決策です。

スレッドが終了したとき、またはタイムアウトしたときに取得して返すThread.Join(int)メソッドを利用 します。millisecond timeouttruefalse

List<Thread> threads = new List<Thread>();

while (!threads.Any(x=> x.Join(100)))
{

}

Joinかかる時間がわかっている場合は、タイムアウトを変更できます。

于 2013-08-25T08:53:38.167 に答える
0

作業スレッドにバックグラウンドワーカーを使用できます。

次に、すべてのRunWorkerCompletedイベントを、それらを待機するメソッドにフックします。

結合を現在待機しているコードに同期させたい場合は、その単一のイベント メソッドをコード内のその場所に同期させるだけで問題は軽減されます。

さらに良いことに、ブロックせずに非同期で実行し、イベントで必要なことを実行することをお勧めします。

于 2013-08-25T08:56:06.233 に答える