スレッドは複数のThreadAbortexceptionを投げることができますか?
-
28-09-2019 - |
質問
これがこのタイプの質問の正しいフォーラムであるかどうかはわかりませんが、現在、メモリダンプを使用してWebサービスで再現できないバグを見つけようとしています。いくつかの入力があるかもしれません。
windbgを使用してメモリダンプを分析すると、メモリにaprox 75000 threadabortexceptionsが見つかります。これらはすべてここから発生します。
at System.Threading.WaitHandle.WaitOne(Int64 timeout Boolean exitContext)
at MyNameSpace.CustomThreadPool.Run()
それらはすべて、アプリケーションがAppDomainを降ろそうとしているときに非常に短い期間に作成されます(IISは閉鎖されています)。
私が今理解できないのは、非常に多くのThreadAbortexceptionsをどのように高めることができるかということです。スレッドが終了した場合、複数の方法を上げる方法はありますか?誰かがこのタイプの非常に多くの例外が存在する理由についてのヒントを与えることができるなら?私が見ることができるものから、最大約20のスレッドがこのプロセスであり、ThreadPool自体にこれが発生したときに1つの(!)スレッドしかありません。
customthreadpoolクラスは、この記事から来ています。http://msdn.microsoft.com/en-us/magazine/cc163851.aspx
public sealed class CustomThreadPool : IDisposable
{
private Semaphore _workWaiting;
private Queue<WaitQueueItem> _queue;
private List<Thread> _threads;
public CustomThreadPool(int numThreads)
{
if (numThreads <= 0)
throw new ArgumentOutOfRangeException("numThreads");
_threads = new List<Thread>(numThreads);
_queue = new Queue<WaitQueueItem>();
_workWaiting = new Semaphore(0, int.MaxValue);
for (int i = 0; i < numThreads; i++)
{
Thread t = new Thread(Run);
t.IsBackground = true;
_threads.Add(t);
t.Start;
}
}
public void Dispose()
{
if (_threads != null)
{
_threads.ForEach(delegate(Thread t) { t.Interrupt(); });
_threads = null;
}
}
public void QueueUserWorkItem(WaitCallback callback, object state)
{
if (_threads == null)
throw new ObjectDisposedException(GetType().Name);
if (callback == null) throw new ArgumentNullException("callback");
WaitQueueItem item = new WaitQueueItem();
item.Callback = callback;
item.State = state;
item.Context = ExecutionContext.Capture();
lock(_queue) _queue.Enqueue(item);
_workWaiting.Release();
}
private void Run()
{
try
{
while (true)
{
_workWaiting.WaitOne();
WaitQueueItem item;
lock(_queue) item = _queue.Dequeue();
ExecutionContext.Run(item.Context,
new ContextCallback(item.Callback), item.State);
}
}
catch(ThreadInterruptedException){}
}
private class WaitQueueItem
{
public WaitCallback Callback;
public object State;
public ExecutionContext Context;
}
}
解決
キャッチしてからリセットすることが可能です ThreadAbortException
使用 Thread.ResetAbort
. 。したがって、単一のスレッドは、実際にそのような例外を多く投げかけることができます。
たとえば、電話する場合 Response.Redirect(url, true)
ASP.NETでは、現在のスレッドを中止してから、中止をより高くキャンセルします。
これがあなたの状況をまったく説明しているかどうかはわかりませんが、見る価値があります。あるいは、アプリドメインがアンロードされているため、スレッドプールが「クラッシュ」したときにスレッドプールを再現しようとしているものはありますか?
編集:あなたのコメントに応答する: AppDomain.Unload
ドキュメンテーション:
ドメイン内のスレッドは、スレッドにthreadebortexceptionをスローするAbortメソッドを使用して終了します。スレッドは迅速に終了するはずですが、最終的に句で予測不可能な時間の実行を続けることができます。
基本的に、スレッドは、AppDomainがアンロードされているため、まさに中止されています。
他のヒント
respons.redirect( "〜/where.aspx")を実行すると、現在(デフォルト)スレッドがまだ実行が終了していない場合、threadabortexceptionを引き起こすことがあります。
過負荷のリダイレクト法を使用して、これを防ぐことができます。
Response.Redirect("~/Somewhere.aspx", false);