我们使用命名管道在C#.Net服务和本机C ++应用程序之间进行通信。该服务创建一个消息模式管道,然后启动计时器。
m_pipeServer = new NamedPipeServerStream ("Cyber_Srv_EventPipe",
PipeDirection.InOut,
1,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous,
4096,
4096,
pipeSa);
m_OutputQueue = new List<My_Message>();
在计时器滴答程序中,主要服务循环如下所示:
do
{
if (!m_bClientAttached)
{
try
{
m_pipeServer.WaitForConnection ();
m_bClientAttached = true;
}
catch (InvalidOperationException invope)
{
sDebug = string.Format ("Pipe wait exception InvOpEx: {0}",
invope.Message);
DebugMessage (sDebug);
}
}
// the message-pumping part of the loop.
if (m_bClientAttached)
{
try
{
if (!m_bReadInProgress)
{
m_bReadInProgress = true;
m_pipeServer.BeginRead (byNewRead, 0, byNewRead.GetLength (0),
new AsyncCallback (this.PipeReadComplete),
m_iReadCount);
}
if (m_OutputQueue.Count () > 0)
{
if (!m_bWriteInProgress)
{
m_bWriteInProgress = true;
My_Message opmsg = m_OutputQueue.ElementAt (0);
m_pipeServer.BeginWrite (opmsg.ToByteArray (), 0,
(int)(opmsg.MsgLength),
new AsyncCallback (this.PipeWriteComplete),
m_iWriteCount);
}
}
}
catch (IOException ioe)
{
sDebug = string.Format ("Main loop raised exception: {1}",
ioe.Message);
DebugMessage (sDebug);
DetachClientPipe();
}
Thread.Sleep(1);
}
} while (m_bRunning);
m_pipeServer.Close ();
}
读写完成例程如下所示:
private void PipeReadComplete (IAsyncResult iAR)
{
string sDebug;
int iByteCount;
My_Message ipmsg = new My_Message();
try
{
iByteCount = m_pipeServer.EndRead (iAR);
if (iByteCount > 0)
{
ipmsg.FromByteArray(byNewRead);
m_bReadInProgress = false;
... process message ...
}
else
{
try
{
DebugMessage ("PRC: Zero bytes read, disconnect pipe");
DetachClientPipe();
}
catch (InvalidOperationException invope)
{
sDebug = string.Format ("PRC - Pipe disconnect exception: {0}",
invope.Message);
DebugMessage (sDebug);
}
}
}
catch (IOException e)
{
sDebug = string.Format ("PRC: Read {0} raised exception: {1}",
(int)(iAR.AsyncState),
e.Message);
DebugMessage (sDebug);
DetachClientPipe();
}
}
// ------------------------------------------------------------------
private void PipeWriteComplete (IAsyncResult iAR)
{
string sDebug;
try
{
m_pipeServer.EndWrite (iAR);
lock (m_OutputQueue)
{
m_OutputQueue.RemoveAt(0);
}
m_bWriteInProgress = false;
}
catch (IOException e)
{
sDebug = string.Format ("Write {0} raised exception: {1}",
(int)(iAR.AsyncState),
e.Message);
DebugMessage (sDebug);
DetachClientPipe();
}
}
// ------------------------------------------------------------------
private void DetachClientPipe()
{
if (m_pipeServer.IsConnected)
{
m_pipeServer.Disconnect();
}
m_bClientAttached = false;
}
客户端代码是已知的好代码,重用。所以这就是问题所在。客户端可以很好地连接。然后我们关闭了客户端,一切都很好。我们重新启动它。一切都很好,然后我们关闭它并重新开始。繁荣 - 错误231,管道忙。服务器现在会在任何连接尝试时生成管道繁忙错误,直到地狱结束,或者我们重新启动服务。然后我们又回到了两个连接。
我已经连续三天盯着这段代码,我不知道为什么会这样做。我似乎无法看到木头的树木,我可以使用一双新鲜的眼睛或三只眼睛。问题是没有 - 团队中的其他任何人都知道任何C#。
更新
在第三次连接尝试失败的原因似乎是在第一次断开连接时PipeReadComplete返回并且我得到零字节读取,所以我分离管道,一切都很好。但是......在第二次断开连接时,PipeReadComplete不会被调用,所以我不强制断开连接。怪异。
答案 0 :(得分:1)
鲍勃,快速修复:想知道,您是否尝试过将服务器实例参数设置为1以上,看看它是否在2次尝试后仍然失败?而不是1,放10,看它是否会有所帮助。此外,如果您发布非托管代码也会有所帮助。我目前正在做同样的事情,Windows服务加上非托管dll IPC。
m_pipeServer = new NamedPipeServerStream ("Cyber_Srv_EventPipe",
PipeDirection.InOut,
10,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous,
4096,
4096,
pipeSa);
或者您实际上只需要一个服务器管道实例?
答案 1 :(得分:0)
请参阅this related question以获取可能的答案。它看起来Suma经历并解决了同样的问题,而不是在C#中,它应该很容易翻译。