我有一个托管线程,它在一个非托管代码中等待,阻塞(具体来说,它在调用NamedPipeServerStream.WaitForConnection()时最终会调用非托管代码,不提供一个超时)。
我想整齐地关闭线程。
Thread.Abort()在代码返回托管领域之前无效,在客户端建立连接之前它不会这样做,我们不能等待。
我需要从非托管代码中“震惊”它;或者即使它处于未管理的土地上也只是杀死线程的方法。
答案 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并自行清理)
这不适用于一般情况(即标题中提出的问题),但它对我有用......