0

これがこの種の質問に対する正しいフォーラムかどうかはわかりませんが、現在、メモリ ダンプを使用して Web サービスで再現できないバグを見つけようとしています。助けが必要な特定の質問があると思います。入力があるかもしれません。

WinDbg を使用してメモリ ダンプを分析すると、メモリ内に約 75000 の ThreadAbortExceptions が見つかり、それらはすべてここから発生します。

at System.Threading.WaitHandle.WaitOne(Int64 timeout  Boolean exitContext)
at MyNameSpace.CustomThreadPool.Run()

それらはすべて、アプリケーションが appdomain をアンロードしようとしている (IIS が終了している) 非常に短い時間で作成されます。

私が今理解できないのは、どのようにして非常に多くの ThreadAbortExceptions を発生させることができるのでしょうか? スレッドが終了した場合、複数のスレッドを発生させる方法はありますか? このタイプの例外が非常に多く存在する理由について、誰かがヒントを与えることができますか? 私が見ることができることから、最大約 20 のスレッドがこのプロセスであり、スレッドプール自体には、これが発生したときに 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;
    }
}
4

2 に答える 2

1

ThreadAbortExceptionを使用してキャッチしてリセットすることができThread.ResetAbortます。したがって、1つのスレッドで、実際にはそのような多くの例外がスローされる可能性があります。

たとえばResponse.Redirect(url, true)、ASP.NETを呼び出すと、現在のスレッドが中止されてから、上位の中止がキャンセルされます。

これがあなたの状況を完全に説明しているのかどうかはわかりませんが、一見の価値があります。または、アプリドメインがアンロードされたためにスレッドプールが「クラッシュ」したときに、スレッドプールを再作成しようとしているものはありますか?

編集:あなたのコメントに返信するには:AppDomain.Unloadドキュメントに従って:

ドメイン内のスレッドは、スレッドでThreadAbortExceptionをスローするAbortメソッドを使用して終了します。スレッドはすぐに終了する必要がありますが、finally句で予測できない時間実行を続けることができます。

基本的に、appdomainがアンロードされているため、スレッドは正確に中止されます。

于 2010-06-21T08:29:48.370 に答える
0

Response.Redirect( "〜/ Somewhere.aspx")を実行すると、現在の(デフォルトの)スレッドがまだ実行を終了していない場合にThreadAbortExceptionが発生することがあります。

オーバーロードされたリダイレクトメソッドを使用することで、これを防ぐことができます。

Response.Redirect("~/Somewhere.aspx", false);
于 2010-06-21T08:52:08.477 に答える