代码之家  ›  专栏  ›  技术社区  ›  James Curran

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

  •  7
  • James Curran  · 技术社区  · 16 年前

    我有一个托管线程,它在非托管代码中等待、阻塞(特别是在调用NamedPipeServerStream.WaitForConnection()时,它最终调用非托管代码,并且 提供超时)。

    在代码返回到托管领域之前,Thread.Abort()没有任何作用,而在客户端建立连接之前,它不会这样做,这是我们不能等待的)。

    我需要一种从非托管代码中“震惊”它的方法;或者在线程处于非托管状态时终止线程。

    3 回复  |  直到 16 年前
        1
  •  20
  •   dtb    16 年前

    你试过用非阻塞的吗 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();
    }
    
        2
  •  1
  •   Jeffrey L Whitledge    16 年前

    你应该使用 BeginWaitForConnection 相反。

        3
  •  0
  •   James Curran    16 年前

    实际上,我使用的解决方案(在我写问题时想到的)是,在中止所有线程之后,为每个线程创建(并立即处理)一个客户机。

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

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

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