开发者

How to terminate a managed thread blocked in unmanaged code?

开发者 https://www.devze.com 2022-12-27 18:58 出处:网络
I have a managed thread which is wai开发者_StackOverflowting, blocked, in an unmanaged code (specifically, it on a call to NamedPipeServerStream.WaitForConnection() which ultimitely calls into unmanag

I have a managed thread which is wai开发者_StackOverflowting, blocked, in an unmanaged code (specifically, it on a call to NamedPipeServerStream.WaitForConnection() which ultimitely calls into unmanaged code, and does not offer a timeout).

I want to shut the thread down neatly.

Thread.Abort() has no effect until the code returns to the managed realm, which it won't do until a client makes a connection, which we can't wait for).

I need a way "shock" it out of the unmanaged code; or a way to just kill the thread even while it's in unmanaged land.


Have you tried using the non-blocking NamedPipeServerStream.BeginWaitForConnection method?

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

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

You don't necessarily have to use a fixed timeout. You can use a ManualResetEvent to signal when the thread should stop waiting for the connection:

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();
}


There is no way to "neatly" shut down a thread from the outside, if that thread is running unmannaged code. There are a couple of ways to abruptly Terminate the thread, but that's probably not what you want.

You should use BeginWaitForConnection instead.


Actually, the solution I used (which occurred to me as I was writing up the question), was to, after aborting all the threads, just to create (and immediately dispose) a client for each thread.

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

With the connection, it returns to managed code, and the Abort() kicks in (the thread catches ThreadAbortException and cleans itself up)

This doesn't work for the general case (i.e., the question posed in the title), but it works for me...

0

精彩评论

暂无评论...
验证码 换一张
取 消