C++ named pipe server code
this code is executed once.
LPTSTR lpszPipename = "\\\\.\\Pipe\\D2MSPipe";
hPipe = ::CreateNamedPipe(lpszPipename,
                            PIPE_ACCESS_OUTBOUND,
                            PIPE_TYPE_MESSAGE,    // | PIPE_READMODE_MESSAGE,
                            PIPE_UNLIMITED_INSTANCES,
                            4096,
                            4096,
                            0,
                            NULL);
bool b = ConnectNamedPipe(hPipe, NULL);
From here, the server waits for the client to connect. Which makes sense.
When the client is connected, here is the C++ code to send data
LPTSTR data = "Hello";
DWORD bytesWritten = 0;
WriteFile(hPipe, data, strlen(data) * sizeof(TCHAR), &bytesWritten, NULL);
Here, bytesWritten contains 5.
Heres my C# client form
using (NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "D2MSPipe", PipeDirection.In))
{
    pipeClient.Connect();
    StreamReader reader = new StreamReader(pipeClient);
    while (true)
    {
        if (reader.Peek() > -1) { 
            byte[] data = new byte[5];
            try
            {
                int wtf = pipeClient.Read(data, 0, 5);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
    pipeClient.Close(); // this doesn't make sense but whatever for now.
}
int wtf = pipeClient.Read(data, 0, 5);
This line hangs. It doesn't throw an exception.
When I step into this instruction, it just does nothing, the data is never assigned/available in the byte array, the code stops executing.
I've tried multiple way to read, with a stream, with no stream, with ReadLine, ReadToEnd...
Everything hangs.
The client has a while loop because the server is going to send data every minute or so. So I assumed I needed to connect only once and create only one StreamReader and peek in a loop to read the incoming data.