杀死一个线程而不影响当前线程

时间:2015-01-31 10:28:54

标签: c# multithreading

每个人都知道线程应该优雅地退出,但现在我必须杀死一个线程。

当有请求提交时,我启动一个如下的线程

_thread = new Thread(ProcessTemplate);
_thread.Start();

ProcessTemplate方法中,它使用Google V8编译并运行从客户端发送的javascript代码。

问题是,从客户端发送的javascript可能是错误的并导致无限循环。

因此,我计算自线程启动以来的时间,如果javasctript执行时间超过10秒,我就像

一样杀死线程
try
{
    _thread.Abort();
}
catch
{
}

它有效,但也会影响启动_thread的当前线程。 我收到“线程被中止”。来自当前线程的异常。

如何避免/忽略异常?

3 个答案:

答案 0 :(得分:3)

  

我收到"线程被中止。"来自当前线程的异常。

您在后台线程中收到此异常,而不是在以the documentation explains启动它的主线程中:

  

在调用它的线程中引发ThreadAbortException   开始终止线程的过程。调用此方法   通常终止线程。

所以在这个后台线程中你可以处理这个异常:

_thread = new Thread(() => 
{
    try
    {
        ProcessTemplate();
    }
    catch (ThreadAbortException ex)
    {
        // the thread was aborted, call ResetAbort to 
        // avoid rethrowing the exception
        Thread.ResetAbort();
    }
);

可能您看到主线程受到影响,因为在某些情况下,后台线程中未处理的异常可能会导致AppDomain失效。所以通常你应该处理这些例外。

答案 1 :(得分:0)

您可以使用Task并将其传递给CancellationToken

Link

答案 2 :(得分:0)

  

我收到"线程被中止。"来自当前线程的异常。

因为当您致电Thread.Abort时会发生什么:

  

在线程上调用此方法时,系统会抛出一个   线程中的ThreadAbortException中止它。 ThreadAbortException   是一个特殊异常,可以被应用程序代码捕获,但是   除非调用ResetAbort,否则在catch块的末尾重新抛出。

您应该在后台线程中捕获ThreadAbortException并确保其已处理。

我建议不要使用the rather dangerous abort,而是使用允许合作取消的Task Parallel Library新功能:

var cts = new CancellationTokenSource();
var ct = cts.Token;
var javaScriptTask = await Task.Run(() => ProcessTemplate, cts.Token);

ProcessTemplate内,监控CancellationToken

ct.ThrowIfCancellationRequest();

或者,如果您在进行阻止调用时确实需要完全控制,则应该启动一个新进程来运行任务。