线程可以抛出多个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本身只有一个(!)线。
costilthreadpool类来自本文: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。尽管该线程应迅速终止,但它可以在最后条款中继续执行不可预测的时间。
基本上,由于您的应用程序被卸载,因此线程正在流产。
其他提示
如果当前(默认)线程尚未完成执行,则执行响应。redirect(“〜/where where.aspx”)有时会导致threadabortexception。
您可以使用超载重定向方法来防止这种情况。
Response.Redirect("~/Somewhere.aspx", false);