一个线程是否可以抛出多个 ThreadAbortException?
我不确定这是否是此类问题的正确论坛,但我目前正在尝试找到一个我无法使用内存转储在网络服务中重现的错误,并且我认为我有一个需要帮助的特定问题,我认为有人可能有一些意见。
使用 WinDbg 分析内存转储,我发现内存中大约有 75000 个 ThreadAbortException,它们都源自这里:
at System.Threading.WaitHandle.WaitOne(Int64 timeout Boolean exitContext)
at MyNameSpace.CustomThreadPool.Run()
它们都是在应用程序尝试卸载其应用程序域(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;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
可以使用 “nofollow noreferrer”>
Thread.ResetAbort
。因此,单个线程实际上可能会抛出许多此类异常。例如,如果您在 ASP.NET 中调用 Response.Redirect(url, true),它将中止当前线程,然后取消更高层的中止。
我不确定这是否能完全解释您的情况,但值得一看。或者,当由于应用程序域被卸载而“崩溃”时,是否尝试重新创建线程池?
编辑:要回复您的评论:按照
AppDomain.Unload
文档:基本上,线程被中止正是因为您的应用程序域正在被卸载。
It's possible to catch and then reset a
ThreadAbortException
usingThread.ResetAbort
. So a single thread could actually have many such exceptions thrown on it.For example, if you call
Response.Redirect(url, true)
in ASP.NET, it will abort the current thread and then cancel the abort higher up.I'm not sure this quite explains your situation, but it's worth looking at. Alternatively, is something trying to recreate the thread pool when it "crashes" due to the app domain being unloaded?
EDIT: To respond to your comment: as per the
AppDomain.Unload
documentation:Basically the threads are being aborted precisely because your appdomain is being unloaded.
如果当前(默认)线程尚未完成执行,则执行 Response.Redirect("~/Somewhere.aspx") 有时会导致 ThreadAbortException。
您可以通过使用重载的重定向方法来防止这种情况。
Doing a Response.Redirect("~/Somewhere.aspx") sometimes causes a ThreadAbortException if the current (default) thread hasn't finished execution yet.
You can prevent this by using the overloaded redirect method.