Может ли нить когда-либо бросить больше, чем один ThreadabortException?

StackOverflow https://stackoverflow.com/questions/3083062

  •  28-09-2019
  •  | 
  •  

Вопрос

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

Анализируя дамп памяти с помощью WINDBG, я нахожу Fromox 75000 Threadabortexceptions в памяти, и все они возникают отсюда:

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

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

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

Класс CustomththreadPool исходит из этой статьи: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 документация:

Нитки в домене прекращаются с помощью метода прерывания, который бросает ThreadabortException в потоке. Хотя нить должна быстро прекращаться, она может продолжать выполняться для непредсказуемого количества времени в краткосрочном пункте.

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

Другие советы

Делать ответ ..redirect («~ / quewway.aspx») иногда вызывает ThreadabortException, если текущий (по умолчанию) нить еще не закончил выполнение.

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

Response.Redirect("~/Somewhere.aspx", false);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top