Reputation: 31
I'm working on a simple software in c# that read bytes from a named pipe (client) and forward it to a serial port (with some processing on the data) and vice-versa. It look like:
if(data available on the named pipe)
write on com port (the data read from the named pipe)
if(data available on the com port)
write on named pipe (the data read from the com port)
repeat endlessly
The problem is that read from the named pipe get blocked if their is no data to read, until a data comes. So the other side communication (com port to pipe) is also blocked.
I have tried running both direction communication in it's own thread, but the write operation on the pipe is blocked while a read operation is performed (or waiting for data) on the other thread. I've tried stopping the blocked thread and cancelling the read operation without success.
The simplest way to deal with this kind of thing would be to either:
get the number of byte available to read on the pipe, and skip reading if 0
or have a timeout on the read operation, so write could occur after the timeout (timing is not that critical in this application).
This work great with the com port part as a comPort.BytesToRead variable containing the number of byte in the read buffer exist.
The named pipe is a client (server created by another software), but could also be a server if this is more convenient.
Any ideas ?!? Thank you in advance !
Upvotes: 2
Views: 4568
Reputation: 31
Thank's Damien, your answer doesn't help me a lot, but I figured it out myself: I've tried working around with readAsync but it wasn't working great because my pipe wasn't opened as Asynchronous:
pipe = new NamedPipeClientStream(".", "thePipe", PipeDirection.InOut, PipeOptions.Asynchronous);
Then, to read the pipe without blocking:
pipe.ReadAsync (buffer, 0, buffer.Lenght).ContinueWith (t=>
{
//called when read is finished (data available).
});
And finally, as the read is called in a while(1) loop, I need to prevent the read async to be lunched multiple times :
if (readFinished) {
readFinished = false;
pipe.ReadAsync (buffer, 0, buffer.Length).ContinueWith (t => {
//called when read is finished (data available).
//TODO: deal with the data (stored in 'buffer').
readFinished = true;
});
}
(with 'readFinished' a boolean initialised to true).
Hope it will help someone else.
Upvotes: 1
Reputation: 239704
I have tried running both direction communication in it's own thread, but the write operation on the pipe is blocked while a read operation is performed (or waiting for data) on the other thread
Pipes can be used to both read and write at the same time, provided the right options are used. Here's a toy sample that demonstrates the client and the server disagreeing on which order they'll be performing operations and it just working:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.IO.Pipes;
using System.Text;
using System.Threading;
public class Bob
{
static void Main()
{
var svr = new NamedPipeServerStream("boris", PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte);
var helper = Task.Run(() =>
{
var clt = new NamedPipeClientStream("localhost", "boris", PipeDirection.InOut, PipeOptions.Asynchronous);
clt.Connect();
var inBuff = new byte[256];
var read = clt.ReadAsync(inBuff, 0, inBuff.Length);
var msg = Encoding.UTF8.GetBytes("Hello!");
var write = clt.WriteAsync(msg, 0, msg.Length);
Task.WaitAll(read, write);
var cltMsg = Encoding.UTF8.GetString(inBuff, 0, read.Result);
Console.WriteLine("Client got message: {0}", cltMsg);
});
svr.WaitForConnection();
var srvBuff = new byte[256];
var srvL = svr.Read(srvBuff, 0, srvBuff.Length);
var svrMsg = Encoding.UTF8.GetString(srvBuff, 0, srvL);
Console.WriteLine("Server got message: {0}", svrMsg);
var response = Encoding.UTF8.GetBytes("We're done now");
svr.Write(response, 0, response.Length);
helper.Wait();
Console.WriteLine("It's all over");
Console.ReadLine();
}
}
(In real world usage, we'd use some async
methods to launch the read and write "threads" rather than manually managing either threads or tasks)
Upvotes: 2