2010-06-21 2 views
0

Im не уверен, что это правильный форум для этого типа вопросов, но Im в настоящее время пытается найти ошибку, которую я не могу воспроизвести в веб-службе, используя дамп памяти, и я думаю, что у меня есть конкретный вопрос, в котором мне нужна помощь, что я подумайте, что у кого-то может быть некоторый вклад.Может ли поток когда-либо бросать больше одного ThreadAbortException?

Анализ дампа памяти с помощью WinDbg я нахожу приблиз 75000 ThreadAbortExceptions в памяти, и все они происходят здесь:

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

Все они созданы в течение очень короткого периода времени, когда приложение пытается выгрузите его appdomain (IIS закрывается).

Что я не могу понять сейчас, так это, как можно увеличить столько ThreadAbortExceptions? Если поток завершает работу, есть ли способ, который может вызвать более одного? Если кто-нибудь может дать какой-либо намек на то, почему так много исключений такого типа могут существовать? Из того, что я вижу, существует около 20 потоков max, это процесс, и сам threadpool имеет только один (!) Поток, когда это происходит.

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; 
    } 
} 

ответ

1

Это можно поймать, а затем сбросить ThreadAbortException с помощью Thread.ResetAbort. Таким образом, на одном потоке может быть много таких исключений, наложенных на него.

Например, если вы вызываете Response.Redirect(url, true) в ASP.NET, он отменяет текущий поток и отменяет отмену выше.

Я не уверен, что это вполне объясняет вашу ситуацию, но стоит посмотреть. Альтернативно, что-то пытается воссоздать пул потоков, когда он «сбой» из-за разгрузки домена приложения?

EDIT: Для того, чтобы ответить на ваш комментарий: согласно документации AppDomain.Unload:

нити в области оканчиваются с использованием метода Abort, который бросает ThreadAbortException в потоке. Несмотря на то, что поток должен немедленно завершить , он может продолжить выполнение за непредсказуемое время в a finally.

В основном потоки прерываются именно потому, что ваш апдомен разгружается.

+0

Спасибо большое за этот ввод, я не знал о Thread.Abort! Однако я не могу найти никакого использования этого в коде, который у меня есть. Есть ли какая-то причина, которая может сделать сама структура? Я посмотрел на Respose.Redirect, Response.End и Server.Transfer, но я не могу найти там никаких обычаев. Отдых - это то, что я собираюсь изучить, спасибо. – MatteS

+0

Если бассейн был воссоздан каждые x минут, например, и, тем самым, новый поток, не существует ли максимум потоков, которые могут существовать, или возможно иметь целых 75000 потоков? В настоящее время я просматриваю код, который может предполагать воссоздание с временными интервалами. – MatteS

+0

@MatteS: Смотрите мое редактирование. Я сомневаюсь, что у вас будет 75000 потоков - мое подозрение в том, что что-то реагирует на поток, прерывая его, снова запустив его, а затем AppDomain.Unload повторно отменяет его и т. Д. –

0

Выполнение Response.Redirect ("~/Somewhere.aspx") иногда вызывает ThreadAbortException, если текущий (по умолчанию) поток еще не завершил выполнение.

Вы можете предотвратить это, используя перегруженный метод перенаправления.

Response.Redirect("~/Somewhere.aspx", false);