Reputation: 164
I'm writing a C# Windows Service (server) that will need to receive messages from C++ GUI applications (clients) using a Named Pipe very infrequently; it could be days to weeks before a message is received. In my testing I noticed that instead of blocking for data to come in, it just continually checks and prints newlines. It does receive the test message but I had to use the debugger in Visual Studio to verify.
Is there a way to get the C# portion to block until there is actually data to be received?
--C# Code:
var client = new NamedPipeServerStream("PipeTest");
client.WaitForConnection();
StreamReader reader = new StreamReader(client);
while (true)
{
Console.WriteLine(reader.ReadLine());
}
--C++ Code:
DWORD written;
INT error_code;
CHAR buffer[1024];
LPCWSTR pipe_name = L"\\\\.\\pipe\\PipeTest";
LRESULT result;
WaitNamedPipe(pipe_name, NMPWAIT_WAIT_FOREVER);
HANDLE hpipe = CreateFile(pipe_name,
GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
error_code = GetLastError();
sprintf_s(buffer,"Sending Test Message");
WriteFile(hpipe,buffer,strlen(buffer),&written,NULL);
result = GetLastError();
fprintf(stdout,"Pipe: %d Write: %d Written: %d",error_code,result,written);
DisconnectNamedPipe(hpipe);
CloseHandle(hpipe);
std::cin.get();
[ANSWER]
--C# Code(server) with corrected names:
var server = new NamedPipeServerStream("PipeTest");
while (true)
{
server.WaitForConnection();
StreamReader reader = new StreamReader(server);
Console.WriteLine(reader.ReadLine());
server.Disconnect();
}
For this code I'll only need to capture one line worth of data, @The Shooter was correct but you'll need to add server.Disconnect()
in order to read again. I found this from the C documentation and the same principle works in C# apparently.
The server process must call
DisconnectNamedPipe
to disconnect a pipe handle from its previous client before the handle can be connected to another client by using theConnectNamedPipe
function.
Upvotes: 0
Views: 1465
Reputation: 733
Instead of:
var client = new NamedPipeServerStream("PipeTest");
client.WaitForConnection();
StreamReader reader = new StreamReader(client);
while (true)
{
Console.WriteLine(reader.ReadLine());
}
Try this:
var client = new NamedPipeServerStream("PipeTest");
while (true)
{
client.WaitForConnection();
StreamReader reader = new StreamReader(client);
Console.WriteLine(reader.ReadLine());
}
Upvotes: 1
Reputation: 36348
The client end is disconnecting the pipe, so the server sees the end of the input stream immediately after the test message is received.
The documentation for StreamReader.ReadLine() says:
The next line from the input stream, or null if the end of the input stream is reached.
So ReadLine
is returning null
; what does Console.WriteLine(String) do in that case?
If value is null, only the line terminator is written to the standard output stream.
QED. The behaviour you're seeing is exactly as expected.
You need to check the value returned from ReadLine
and deal with null
appropriately. In this case you presumably want to wait for another connection.
Upvotes: 2