我不确定这是这类问题的正确论坛,但我目前正试图找到一个我无法在使用内存转储的Web服务中重现的错误,我想我有一个我需要帮助的具体问题,我想有人可能会有一些意见。
使用WinDbg分析内存转储我在内存中找到aprox 75000 ThreadAbortExceptions,它们都来自这里:
at System.Threading.WaitHandle.WaitOne(Int64 timeout Boolean exitContext)
at MyNameSpace.CustomThreadPool.Run()
当应用程序尝试卸载其appdomain(IIS正在关闭)时,它们都是在很短的时间内创建的。
我现在无法弄清楚如何筹集如此多的ThreadAbortExceptions?如果线程退出,是否有任何方式可以引发多个线程?如果有人可以提供任何暗示,为什么存在这种类型的这么多例外?从我可以看到,这个过程最多有20个线程,并且线程池本身只有一个(!)线程。
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;
}
}
答案 0 :(得分:1)
可以使用Thread.ResetAbort
捕捉并重置ThreadAbortException
。因此,单个线程实际上可能会抛出许多此类异常。
例如,如果在ASP.NET中调用Response.Redirect(url, true)
,它将中止当前线程,然后取消更高的中止。
我不确定这会解释你的情况,但值得一看。或者,当由于应用程序域被卸载而导致“崩溃”时,是否会尝试重新创建线程池?
编辑:回复您的评论:根据AppDomain.Unload
文档:
域中的线程终止 使用Abort方法,抛出一个 线程中的ThreadAbortException。 虽然线程应该终止 及时,它可以继续执行 在一段不可预测的时间里 最后一句。
基本上,线程正在被中止,因为你的appdomain正在被卸载。
答案 1 :(得分:0)
如果当前(默认)线程尚未完成执行,则执行Response.Redirect(“〜/ Somewhere.aspx”)有时会导致ThreadAbortException。
您可以使用重载重定向方法来阻止这种情况。
Response.Redirect("~/Somewhere.aspx", false);