代码之家  ›  专栏  ›  技术社区  ›  MatteS

一个线程能抛出多个ThreadAbortException吗?

  •  0
  • MatteS  · 技术社区  · 14 年前

    我不确定这是正确的论坛为这种类型的问题,但我目前正在试图找到一个错误,我不能复制在一个网络服务使用内存转储,我想我有一个具体的问题,我需要帮助,我想有人可能有一些意见。

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

    它们都是在应用程序试图卸载其appdomain(IIS正在关闭)的很短时间内创建的。

    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;
        }
    }
    
    2 回复  |  直到 14 年前
        1
  •  1
  •   Jon Skeet    14 年前

    可以捕捉并重置 ThreadAbortException 使用 Thread.ResetAbort . 所以一个线程实际上可能会抛出许多这样的异常。

    例如,如果你打电话 Response.Redirect(url, true) 在ASP.NET中,它将中止当前线程,然后取消更高级别的中止。

    编辑:回复您的评论:根据 AppDomain.Unload 文档:

    域中的线程被终止 使用Abort方法 线程中的ThreadAbortException。 很快,它就可以继续执行 在一段不可预知的时间里 最后一句。

    基本上,线程被中止正是因为你的appdomain正在被卸载。

        2
  •  0
  •   Damien Dennehy    14 年前

    如果当前(默认)线程尚未完成执行,执行Response.Redirect(“~/Somewhere.aspx”)有时会导致ThreadAbortException。

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