如何终止在非托管代码中阻止的托管线程?

时间:2010-04-23 17:03:03

标签: c# .net multithreading

我有一个托管线程,它在一个非托管代码中等待,阻塞(具体来说,它在调用NamedPipeServerStream.WaitForConnection()时最终会调用非托管代码,提供一个超时)。

我想整齐地关闭线程。

Thread.Abort()在代码返回托管领域之前无效,在客户端建立连接之前它不会这样做,我们不能等待。

我需要从非托管代码中“震惊”它;或者即使它处于未管理的土地上也只是杀死线程的方法。

3 个答案:

答案 0 :(得分:19)

您是否尝试过使用非阻止NamedPipeServerStream.BeginWaitForConnection方法?

using (NamedPipeServerStream stream = ...)
{
    var asyncResult = stream.BeginWaitForConnection(null, null);

    if (asyncResult.AsyncWaitHandle.WaitOne(5000))
    {
        stream.EndWaitForConnection(asyncResult);
        // success
    }
}

您不一定要使用固定超时。当线程停止等待连接时,您可以使用ManualResetEvent发出信号:

ManualResetEvent signal = new ManualResetEvent(false);

using (NamedPipeServerStream stream = ...)
{
    var asyncResult = stream.BeginWaitForConnection(_ => signal.Set(), null);

    signal.WaitOne();
    if (asyncResult.IsCompleted)
    {
        stream.EndWaitForConnection(asyncResult);
        // success
    }
}

// in other thread
void cancel_Click(object sender, EventArgs e)
{
    signal.Set();
}

答案 1 :(得分:1)

如果该线程正在运行非托管代码,则无法从外部“整齐地”关闭线程。有几种方法可以突然终止线程,但这可能不是你想要的。

您应该使用BeginWaitForConnection代替。

答案 2 :(得分:0)

实际上,我使用的解决方案(在我编写问题时发生在我身上)是在中止所有线程之后,只是为每个线程创建(并立即处置)客户端。

  threads.ForEach(thread=> thread.Abort());
  threads.ForEach(thread=>
              {
                   var client = new PipeClient(ServiceName); 
                   client.Connect(); 
                   client.Dispose();
              });

通过连接,它返回到托管代码,并且Abort()启动(线程捕获ThreadAbortException并自行清理)

这不适用于一般情况(即标题中提出的问题),但它对我有用......