我正在使用此代码为另一个线程提供时间限制并在一定时间后中断它:
void RunWithTimeout(Action action, TimeSpan timeout)
{
AutoResetEvent signal = new AutoResetEvent(false);
Thread workerThread = null;
ThreadPool.QueueUserWorkItem((o) =>
{
workerThread = Thread.CurrentThread;
action();
signal.Set();
});
using (new Timer((o) => { signal.Set(); }, null, (int)timeout.TotalMilliseconds, Timeout.Infinite))
{
signal.WaitOne();
}
if (workerThread != null && workerThread.IsAlive)
{
try
{
workerThread.Abort();
}
catch { }
throw new System.TimeoutException();
}
}
我正在使用.NET 3.5,所以我无法使用任务
我现在正在抛出TimeoutException,但我想知道在调用Abort
时正在执行的行。
有没有办法获取另一个线程的调用堆栈并将其传递给异常的StackTrace
属性?
答案 0 :(得分:2)
您不需要Timer
等待另一个线程,您可以使用接受超时的WaitOne
重载(以毫秒为单位)。
要捕获工作线程上的堆栈跟踪,可以通过闭包变量将ThreadAbortException
传递给主线程:
private static void RunWithTimeout(Action action, TimeSpan timeout)
{
Thread worker = null;
var signal = new AutoResetEvent(false);
ThreadAbortException abortException = null;
ThreadPool.QueueUserWorkItem(o =>
{
worker = Thread.CurrentThread;
try
{
action();
signal.Set();
}
catch (ThreadAbortException ex)
{
//thread is being aborted, pass the exception back to the main thread
abortException = ex;
}
});
if (!signal.WaitOne(timeout))
{
worker.Abort();
//abortException is now filled from the worker thread, the stack trace for the
//worker thread is now inside the InnerException of the ThreadAbortException
throw new TimeoutException("Operation timed out", abortException);
}
}
答案 1 :(得分:1)
您可以尝试捕捉ThreadAbortException
,如下所示:
class Program
{
static void Main(string[] args)
{
var thread = new Thread(Work);
thread.Start();
Thread.Sleep(3000);
thread.Abort();
}
static void Work()
{
try
{
while (true)
{
// do work here
}
}
catch (ThreadAbortException ex)
{
Console.WriteLine(ex.StackTrace);
// TODO: pass ex.StackTrace to main thread
}
}
}
堆栈跟踪将包含线程中止时的方法名称。 ThreadAbortException
将自动重新抛出,因此线程仍然会中止。