我有一个托管自定义用户控件的Windows窗体。此用户控件将启动一个单独的进程(.exe),用于创建和初始化NamedPipeServerStream。一旦进程初始化NamedPipeServerStream,用户控件就会以NamedPipeClientStream的身份连接到它。
一切正常。
在Windows窗体上,我有一个名为“检查更新”的按钮。按下此按钮时,NamedPipeClientStream会向服务器发送一条消息,服务器响应该消息,其中一条消息框说“我已被告知要检查更新”。所以我可以告诉这个客户>服务器通信工作正常。
这是问题所在。然后服务器应该向客户端发送消息BACK,告诉它现在正在检查更新(因此用户控制可以在服务器收到命令后更新其状态)。但是每当发生这种情况时,一切都会锁定。
现在我假设这是因为我试图同时读取和写入命名管道?
以下是服务器和客户端的一些代码段。 (这两个片段在各自的进程中以单独的线程运行,以便不阻止UI)
GUpdater(命名管道服务器):
private void WaitForClientCommands()
{
// Wait for a connection from a Named Pipe Client (The GUpControl)
pipeStream.WaitForConnection();
pipeConnected = true;
// Create a StreamWriter/StreamReader so we can write/read to the Named Pipe
pipeStreamWriter = new StreamWriter(pipeStream) { AutoFlush = true };
pipeStreamReader = new StreamReader(pipeStream);
// Now that we have a connection, start reading in messages and processing them
while (true)
{
// Skip this time if we are currently writing to the pipe
if(isWritingToPipe) continue;
var message = pipeStreamReader.ReadLine();
if (message == null)
{
// We don't want to hog up all the CPU time, so if no message was reaceived this time, wait for half a second
Thread.Sleep(500);
continue;
}
switch(message)
{
case "CheckForUpdates":
//MessageBox.Show("Told to check for updates");
SendMessageToClient("Checking For Updates, Woot!");
break;
case "DownloadUpdate":
MessageBox.Show("Told to download update");
break;
case "ApplyUpdate":
MessageBox.Show("Told to apply update");
break;
}
}
}
GUpControl(命名管道客户端):
private void WaitForServerCommands()
{
if(!pipeConnected) return;
// Now that we have a connection, start reading in messages and processing them
while (true)
{
// Skip this time if we are currently writing to the pipe
if (isWritingToPipe) continue;
// Attempt to read a line from the pipe
var message = pipeStreamReader.ReadLine();
if (message == null)
{
// We don't want to hog up all the CPU time, so if no message was reaceived this time, wait for half a second
Thread.Sleep(500);
continue;
}
MessageBox.Show("I got a message from the server!!\r\n" + message);
}
}
以下代码段是负责从每个组件写入客户端/服务器的方法。 (唯一的区别在于名称,即SendMessageToClient
和SendMessageToServer
)
private void SendMessageToServer(string message)
{
if(pipeConnected)
{
isWritingToPipe = true;
pipeStreamWriter.WriteLine(message);
isWritingToPipe = false;
}
}
isWritingToPipe
变量是一个简单的bool,当相应进程尝试写入命名管道时,该变量为true。这是我最初尝试解决问题的方法。
非常感谢任何帮助!
答案 0 :(得分:1)
System.IO.Pipes.PipeStream
有一个方法WaitForPipeDrain()
,这是在交换消息时管理客户端和服务器之间协调的正确方法。
管道的TransmissionMode也可能会影响一些事情:您使用的是字节模式还是消息模式?例如,我不确定StreamReader中的流包装如何与管道消息模式语义一起播放。有关消息模式的更多信息,请参阅this SO answer。
答案 1 :(得分:0)
当您向服务器发送信号以检查更新时,请在BackgroundWorker类
中执行此操作答案 2 :(得分:0)
解决这个问题的方法是重新考虑软件的设计。
UserControl不是让UserControl在更新过程的每一步都与单独的应用程序对话,而是自己处理它,然后最终需要应用更新时(这涉及覆盖应用程序文件,因此需要单独使用)首先,它只是使用Process.Start(“...”)和一些命令行参数调用一个单独的进程来完成工作。
比尝试为此任务执行进程间通信更简单的解决方案。
尽管如此,我还是很高兴找出为什么我的双向通信无效。