关闭 NamedPipeServer#WaitForConnection 上阻塞的线程的好方法是什么?
我启动我的应用程序,它生成许多线程,每个线程创建一个 NamedPipeServer(.net 3.5 为命名管道 IPC 添加托管类型)并等待客户端连接(块)。 该代码按预期运行。
private void StartNamedPipeServer()
{
using (NamedPipeServerStream pipeStream =
new NamedPipeServerStream(m_sPipeName, PipeDirection.InOut, m_iMaxInstancesToCreate, PipeTransmissionMode.Message, PipeOptions.None))
{
m_pipeServers.Add(pipeStream);
while (!m_bShutdownRequested)
{
pipeStream.WaitForConnection();
Console.WriteLine("Client connection received by {0}", Thread.CurrentThread.Name);
....
现在我还需要一个 Shutdown 方法来彻底关闭这个过程。 我尝试了通常的 bool flag isShutdownRequested 技巧。 但管道流在 WaitForConnection() 调用上保持阻塞状态,并且线程不会终止。
public void Stop()
{
m_bShutdownRequested = true;
for (int i = 0; i < m_iMaxInstancesToCreate; i++)
{
Thread t = m_serverThreads[i];
NamedPipeServerStream pipeStream = m_pipeServers[i];
if (pipeStream != null)
{
if (pipeStream.IsConnected)
pipeStream.Disconnect();
pipeStream.Close();
pipeStream.Dispose();
}
Console.Write("Shutting down {0} ...", t.Name);
t.Join();
Console.WriteLine(" done!");
}
}
加入永不返回。
我没有尝试但可能有效的一个选项是调用 Thread.Abort 并消除异常。 但感觉不太对..有什么建议
更新2009-12-22
抱歉没有早点发布此内容。这是我收到 Kim Hamilton(BCL 团队)的回复
进行可中断的“正确”方法 WaitForConnection 是调用 BeginWaitForConnection,处理新的 回调中的连接,并关闭 要停止等待的管道流 连接。 如果管道被关闭, EndWaitForConnection 将抛出 ObjectDisposeException 其中 回调线程可以捕获、清理 任何未解决的问题,然后干净地退出。
我们意识到这一定是一个常见问题 问题,所以我团队中的某个人 计划很快就此事发表博客。
I start my application which spawns a number of Threads, each of which creates a NamedPipeServer (.net 3.5 added managed types for Named Pipe IPC) and waits for clients to connect (Blocks). The code functions as intended.
private void StartNamedPipeServer()
{
using (NamedPipeServerStream pipeStream =
new NamedPipeServerStream(m_sPipeName, PipeDirection.InOut, m_iMaxInstancesToCreate, PipeTransmissionMode.Message, PipeOptions.None))
{
m_pipeServers.Add(pipeStream);
while (!m_bShutdownRequested)
{
pipeStream.WaitForConnection();
Console.WriteLine("Client connection received by {0}", Thread.CurrentThread.Name);
....
Now I also need a Shutdown method to bring this process down cleanly. I tried the usual bool flag isShutdownRequested trick. But the pipestream stays blocked on the WaitForConnection() call and the thread doesn't die.
public void Stop()
{
m_bShutdownRequested = true;
for (int i = 0; i < m_iMaxInstancesToCreate; i++)
{
Thread t = m_serverThreads[i];
NamedPipeServerStream pipeStream = m_pipeServers[i];
if (pipeStream != null)
{
if (pipeStream.IsConnected)
pipeStream.Disconnect();
pipeStream.Close();
pipeStream.Dispose();
}
Console.Write("Shutting down {0} ...", t.Name);
t.Join();
Console.WriteLine(" done!");
}
}
Join never returns.
An option that I didnt try but would possibly work is to call Thread.Abort and eat up the exception. But it doesn't feel right.. Any suggestions
Update 2009-12-22
Sorry for not posting this earlier.. This is what I received as a response from Kim Hamilton (BCL team)
The "right" way to do an interruptible
WaitForConnection is to call
BeginWaitForConnection, handle the new
connection in the callback, and close
the pipe stream to stop waiting for
connections. If the pipe is closed,
EndWaitForConnection will throw
ObjectDisposedException which the
callback thread can catch, clean up
any loose ends, and exit cleanly.We realize this must be a common
question, so someone on my team is
planning to blog about this soon.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这很俗气,但这是我唯一能发挥作用的方法。 创建一个“假”客户端并连接到命名管道以跳过 WaitForConnection。 每次都有效。
另外,即使 Thread.Abort() 也没有为我解决这个问题。
This is cheesy, but it is the only method I have gotten to work. Create a 'fake' client and connect to your named pipe to move past the WaitForConnection. Works every time.
Also, even Thread.Abort() did not fix this issue for me.
切换到异步版本:
BeginWaitForConnection
。如果它确实完成,您将需要一个标志,以便完成处理程序可以调用
EndWaitForConnection
吸收任何异常并退出(调用 End... 以确保能够清理所有资源)。Switch to the asynchronous version:
BeginWaitForConnection
.If it does ever complete, you'll need a flag so the completion handler can just call
EndWaitForConnection
absorbing any exceptions and exiting (call End... to ensure any resources are able to be cleaned up).您可以使用以下扩展方法。 请注意包含“ManualResetEvent cancelEvent” - 您可以从另一个线程设置此事件,以指示等待的连接方法应立即中止并关闭管道。 设置 m_bShutdownRequested 时包含 cancelEvent.Set(),并且关闭应该相对优雅。
You can use the following extension method. Note the inclusion of 'ManualResetEvent cancelEvent' - you can set this event from another thread to signal that the waiting connect method should abort now and close the pipe. Include cancelEvent.Set() when setting m_bShutdownRequested and the shutdown should be relatively graceful.
我写了这个扩展方法来解决这个问题:
I wrote this extension method to solve this problem:
一个最简单的解决方案是创建一个虚拟客户端并与服务器建立连接。
An simplest and easy solution is creating a dummy client and do a connection with the server.
一种可行的方法是在 WaitForConnection 之后立即检查 m_bShutdownRequested。
在关闭过程中设置布尔值。 之后,向所有现有管道发送虚拟消息,以便它们打开连接并检查布尔值并彻底关闭。
One way that could work is checking for m_bShutdownRequested right after the WaitForConnection.
During the shutdown process set the bool. After that send dummy messages to all the existing pipes so they open the connection and check the bool and shut down cleanly.
//用法,将 ToggleButtons 放入 StackPanel 中,并在代码中支持它们:
//对我来说就像一个魅力。 尊敬的,zzzbc
}
//Usage, Place ToggleButtons inside StackPanel, and back them in code thus:
//Worked like a charm for me. Respectfully, zzzbc
}