一些真实的代码,用于演示GUI应用程序中管道服务器端的异步使用:
void wait_for_object(HANDLE object)
{
DWORD dw;
MSG msg;
for (;;)
{
dw = MsgWaitForMultipleObjectsEx(1, &object, INFINITE, QS_ALLINPUT, 0);
if (dw == WAIT_OBJECT_0) break;
if (dw == WAIT_OBJECT_0 + 1)
{
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
continue;
}
srvfail(L"sleep() messageloop", GetLastError());
}
}
HANDLE server_pipe;
HANDLE io_event;
void pipe_connection(void)
{
OVERLAPPED overlapped;
DWORD dw, err;
SecureZeroMemory(&overlapped, sizeof(overlapped));
overlapped.hEvent = io_event;
if (!ReadFile(server_pipe, input_buffer, sizeof(input_buffer) - 1, NULL, &overlapped))
{
err = GetLastError();
if (err == ERROR_IO_PENDING)
{
wait_for_object(io_event);
if (!GetOverlappedResult(server_pipe, &overlapped, &dw, FALSE))
{
srvfail(L"Read from pipe failed asynchronously.", GetLastError());
}
}
else
{
srvfail(L"Read from pipe failed synchronously.", GetLastError());
}
}
else
{
if (!GetOverlappedResult(server_pipe, &overlapped, &dw, FALSE))
{
srvfail(L"GetOverlappedResult failed reading from pipe.", GetLastError());
}
}
input_buffer[dw] = '\0';
process_command();
if (!WriteFile(server_pipe, &output_struct,
((char *)&output_struct.output_string - (char *)&output_struct) + output_struct.string_length,
NULL, &overlapped))
{
err = GetLastError();
if (err == ERROR_IO_PENDING)
{
wait_for_object(io_event);
if (!GetOverlappedResult(server_pipe, &overlapped, &dw, FALSE))
{
srvfail(L"Write to pipe failed asynchronously.", GetLastError());
}
}
else
{
srvfail(L"Write to pipe failed synchronously.", GetLastError());
}
}
else
{
if (!GetOverlappedResult(server_pipe, &overlapped, &dw, FALSE))
{
srvfail(L"GetOverlappedResult failed writing to pipe.", GetLastError());
}
}
if (!FlushFileBuffers(server_pipe)) srvfail(L"FlushFileBuffers failed.", GetLastError());
if (!DisconnectNamedPipe(server_pipe)) srvfail(L"DisconnectNamedPipe failed.", GetLastError());
}
void server(void)
{
OVERLAPPED overlapped;
DWORD err, dw;
// Create the named pipe
server_pipe = CreateNamedPipe(pipe_name, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, buffer_size, buffer_size, 0, NULL);
if (server_pipe == INVALID_HANDLE_VALUE) srvfail(L"CreateNamedPipe failed.", GetLastError());
// Wait for connections
io_event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (io_event == NULL) srvfail(L"CreateEvent(io_event) failed.", GetLastError());
for (;;)
{
SecureZeroMemory(&overlapped, sizeof(overlapped));
overlapped.hEvent = io_event;
if (!ConnectNamedPipe(server_pipe, &overlapped))
{
err = GetLastError();
if (err == ERROR_PIPE_CONNECTED)
{
pipe_connection();
}
else if (err == ERROR_IO_PENDING)
{
wait_for_object(io_event);
if (!GetOverlappedResult(server_pipe, &overlapped, &dw, FALSE))
{
srvfail(L"Pipe connection failed asynchronously.", GetLastError());
}
pipe_connection();
}
else
{
srvfail(L"Pipe connection failed synchronously.", GetLastError());
}
}
else
{
if (!GetOverlappedResult(server_pipe, &overlapped, &dw, FALSE))
{
srvfail(L"GetOverlappedResult failed connecting pipe.", GetLastError());
}
pipe_connection();
}
}
}
(此代码已从原始代码中删除以删除无关的逻辑。我没有尝试编译编辑版本,因此可能存在一些小问题。还要注意使用全局变量,这在我的情况下可以,因为应用程序非常小,但通常应该避免。)
使用MsgWaitForMultipleObjectsEx()可以在等待I / O完成时处理窗口消息。 如果你还在等待其他事情发生,你可以传递一个句柄数组而不只是一个句柄 - 例如,如果你想监视一个子进程并在它退出时做一些事情,你可以传递一个包含io_event和进程句柄。 如果您只是需要定期执行其他工作,可以设置等待超时,或使用窗口计时器。