![](/img/trans.png)
[英]How do i cancel a backgroundworker operation and how to pause/continue a backgroundworker?
[英]How do I cancel a PIPE operation?
我有一个 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);
所以我的问题是:错误是ERROR_PIPE_LISTENING
在ConnectNamedPipe()
调用之后,发生在我添加PIPE_NOWAIT
。 为什么是那个错误? 我该如何解决? 这是添加支持以取消命名管道操作的正确方法吗? 我会杀死正在运行Listen()
读,但我读到它不是一个好的实践(它甚至不起作用)。
注意:我正在处理现有的代码库,由于时间原因,我希望避免使用NamedPipeClientStream
重写所有内容。
在 C++ 中,您需要使用重叠的 io 创建文件,然后WaitForMultipleObjects(..., INFINITE);
对于停止事件和 IO。
如果你得到停止事件,那么你CancelIO();
.
对于 C# msdn : Overlapped允许您创建重叠对象(读取所需)。
stackoverflow : pinvoke ReadFile 。 这显示了如何使用重叠选项本机调用 ReadFile。
stackoverflow : waitformultipleobjects 功能解释了如何调用 WaitForMultipleObjects。
在解决这类问题时,我创建了一个独立的函数
ReadFileWithEvent( HANDLE file, VOID * pData, size_t data, HANDLE exitEvent, BOOL & signalled );
它打包创建了一个重叠的对象,等待并向调用者解释停止发生,并且读取尚未完成。 这简化了我需要的代码。
我解决了这个与PeekNamedPipe
(),我得到的数量总字节可用,并调用ReadFile
(),只有当它> 0。这是一个简单的方法来模拟非阻塞模式,我可以退出只设置一个线程中运行循环done
到true
。
像这样的东西:
while(!done) {
DWORD total_available_bytes = 0;
if(!PeekNamedPipe(hPipe2, NULL, 0, NULL, &total_available_bytes, NULL)) {
/* error handling goes here */
break;
}
// for avoid overuse of the CPU, sleep for a while until next check.
if(total_available_bytes == 0) {
Sleep(500);
continue;
}
if(ReadFile(hPipe2, ...)) {
// ...
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.