0

編集:これは難点のように思われるので、邪魔にならないようにします:

これを同期には使用していません。長時間実行されるタスクが不要になった/望ましくなくなったときに単純に強制終了します。
仮説的には、これらのスレッドが単純にコンソールに書き込み (「スレッド 1」など)、ランダムな長さだけスリープしてから終了すると仮定します。それらが中止された場合は、別のコンソール書き込みで通知してもらいたいです (たとえば、「スレッド 1 が中止されました」)。また、通常の機能を実行する可能性がなく、実行前に中止しようとした場合に、中止コードに直接ジャンプできるようにしたいと考えています。通常の機能中に中止された場合、もちろん両方を出力します。


Visual Studio 2008 で .NET 2.0 を実行している ASP サイトで、順番に実行したいスレッドのチャンクがあり (どれだけ重要かはわかりませんが、問題はあります)、それらのスレッドにはクリーンアップ コードが中止されている可能性があります。これは、タスクの進行状況に関係なく実行する必要があります。そこで、次のようなスレッドを立てます。

Thread t = new Thread(delegate() {
   try { 
      /* do things */ 
      System.Diagnostics.Debug.WriteLine("try");
   }
   catch (ThreadAbortException) {
      /* cleanup */ 
      System.Diagnostics.Debug.WriteLine("catch");
   }
});

ここで、一連のスレッドを途中で中止したい場合でも、後でクリーンアップを行うことが望ましい場合があります。MSDN を見ると、開始されていないスレッドを .Abort() してから .Start() できることがわかります。この時点で例外を受け取り、正常に実行されます。または、中断されたスレッドを .Join() して、中断が完了するのを待つことができます。おそらく、それらを組み合わせることができます。

http://msdn.microsoft.com/en-us/library/ty8d3wta(v=VS.80).aspx
スレッドが中止されるまで待機するには、Abort メソッドを呼び出した後にスレッドで Join メソッドを呼び出すことができますが、待機が終了する保証はありません。
開始されていないスレッドで Abort が呼び出された場合、そのスレッドは Start が呼び出されたときに中止されます。ブロックされているスレッドまたはスリープしているスレッドで Abort が呼び出されると、スレッドは中断されてから中止されます。

ここで、このコードをデバッグしてステップ実行すると、次のようになります。

t.Abort(); // ThreadState == Unstarted | AbortRequested
t.Start(); // throws ThreadStartException: "Thread failed to start."
// so I comment it out, and
t.Join(); // throws ThreadStateException: "Thread has not been started."

出力がまったく表示されず、try または catch ブロックのブレークポイントにも到達しません。
奇妙なことに、ThreadStartException は .Start() の可能なスローとしてリストされていません。ここから: http://msdn.microsoft.com/en-us/library/a9fyxz7d(v=VS.80).aspx (またはその他のバージョン) )

これは、スレッドがクリーンアップ コードにジャンプする必要があるかどうかを示す start パラメーターを使用し、Abort 呼び出しを前に行うことで回避できることを理解しています (これはおそらく私が行うことです)。そして、スレッドを .Start() してから .Abort() することができましたしかし、.Start と .Abort の間に不確定な時間が経過する可能性があるため、信頼性が低いと考えており、ドキュメントには、私の元の方法が機能するはずであると書かれているようです。

何か不足していますか?ドキュメントは間違っていますか?

編集:ああ。また、パラメーター化されていない Thread(Start) で .Start(param) を呼び出すことはできません。試行錯誤以外に、スレッドがパラメータ化されているかどうかを確認する方法はありますか? プライベート m_Delegate が表示されますが、パブリックはありません...

4

2 に答える 2

3

使用時...

t.Abort();
t.Start();

... ThreadStartExcpetion の innerException には、msdn が述べているように ThreadAbortExeption が含まれます (開始されていないスレッドで Abort が呼び出された場合、Start が呼び出されるとスレッドは中止されます) 。

実行すると...

t.Start();
t.Abort();

... スレッドが中止される前に開始する時間がなかったため、ThreadAbortException が発生しない可能性があります。

次のようなものをテストすると...

t.Start();
Thread.Sleep(100);
t.Abort();

...「クリーンアップ」コードは常に実行する必要があります。

スレッドが何も開始していなくても cleanup-code を実行する必要がある場合、考えられる解決策は、Abort 呼び出しと共にクリーンアップ メソッドを開始することです。

さらに、スレッドの中止を回避し、別の手法を使用するようにしてください (http://msdn.microsoft.com/en-us/library/ms228964.aspx)。

于 2011-01-03T20:57:42.790 に答える
0

ドキュメンテーションがあなたに暗示していることは理解していますが、実際にはそうではありません。スレッドを中止してから開始すると、スレッドはまったく実行されません。CLR は、スレッドの中止が不安定なビジネスであることを十分に認識しており、スレッドの実行を完全にスキップする機会を逃してはなりません。

おそらく、クリーンアップ コードをサブルーチンにします。親スレッドがアボートした場合、またはアボートについて知っている場合は、クリーンアップ コードを明示的に呼び出します。

スレッドを中止した後の「クリーンアップ」の .net の概念は、中止されたスレッドを実行していたアセンブリの appdomain をアンロードすることであることに注意してください。これは、「これがうまくクリーンアップされるとは思わないでください」という別の言い方です。まず、スレッドの中止を必要としない設計を常に探す必要があります。

于 2011-01-03T20:44:25.130 に答える