【发布时间】:2016-01-20 21:03:23
【问题描述】:
我有一个 C++ 和 C# 应用程序,我使用命名管道相互发送命令。它运行良好,直到我注意到我无法取消 Read() 调用,我使用了一个停止变量,但没有注意到这不是我所需要的,因为它无法读取停止变量状态,直到下车Read() 打电话。我发现我会在CreateNamedPipe() 调用中使用PIPE_NOWAIT 属性。当我添加它时,C# 抛出一个 System.NullReferenceException,因为 FileStream 为空,它是从 new FileStream(clientHandle, FileAccess.ReadWrite, BUFFER_SIZE, true); 创建的,其中 clientHandle 创建如下:
private void Listen()
{
while (!exitLoop)
{
clientHandle = CreateNamedPipe(this.pipeName,
DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_NOWAIT,
255,
BUFFER_SIZE,
BUFFER_SIZE,
0,
IntPtr.Zero);
if (clientHandle.IsInvalid)
{
return;
}
int ok = ConnectNamedPipe(clientHandle, IntPtr.Zero);
//could not connect client
if (ok == 0) // here's the error, getLastError() = ERROR_PIPE_LISTENING
{
return;
}
stream = new FileStream(clientHandle, FileAccess.ReadWrite, BUFFER_SIZE, true);
// ....
}
如果重要的话,在 C++ 中管道是这样创建的:
hPipe1 = CreateFile(lpszPipename1,
GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
if (!IsValidPipe(hPipe1))
{
openError();
return;
}
hPipe2 = CreateFile(lpszPipename2,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
所以我的问题是:在ConnectNamedPipe() 调用之后,错误是ERROR_PIPE_LISTENING,发生在我添加PIPE_NOWAIT 之后。为什么会出现这个错误?我该如何解决?这是添加支持以取消命名管道操作的正确方法吗?我会杀死 Listen() 正在运行的 theread,但我读到它不是一个好的实践(它甚至也不起作用)。
注意:我正在处理现有代码库,出于时间原因,我希望避免使用 NamedPipeClientStream 重写所有内容。
【问题讨论】:
-
在非阻塞模式下,ERROR_PIPE_LISTENING 是正常的记录行为;这意味着“目前没有客户端正在尝试连接,请稍后再试”。但是无论如何,您不应该同时使用非阻塞模式和异步模式。异步模式是首选,在这种情况下更是如此,因为 FileStream 类不太可能支持非阻塞模式。
-
C# 应用程序,即客户端,已打开。这就是为什么我没有得到
ConnectNamedPipe()返回值的原因。如果我删除PIPE_NOWAIT属性并使用 0(与PIPE_WAIT相同,默认值),这会很好。我试过这个(pastebin.com/03GhwRnJ)只是想看看它是否在尝试一段时间后连接,但它没有。我将尝试清理同时使用异步模式和非阻塞模式的烂摊子...... -
该 pastebin 代码将不起作用,因为无论使用 ERROR_PIPE_LISTENING (还没有客户端)还是 ERROR_PIPE_CONNECTED (成功!),调用都会返回零,并且您无法区分这两种情况。但这几乎没有实际意义。你真的需要删除
PIPE_NOWAIT。希望 mksteve 的回答能为您提供另一种选择。 -
只是想看看每个
ConnectNamedPipe()之后的最后一个 Windows 错误代码是什么,我运行了这个(pastebin.com/Umk4R4hg)。我得到ERROR_PIPE_LISTENING一段时间然后ERROR_PIPE_CONNECTED。如果 Windows 最后一个错误代码是ERROR_PIPE_CONNECTED则中断循环,我稍后会在stream.Read()调用时遇到异常。我要删除PIPE_NOWAIT并尝试 mksteve 的回答。
标签: c# c++ windows multithreading named-pipes