I have a windows service and a GUI that need to communicate with each other. Either can send messages at any time.
I'm looking at using NamedPipes, but it seems that you cant read & write to the stream at the same time (or at least I cant find any examples that cover this case).
Is it possible to do this kind of two-way communication via a single NamedPipe? Or do I need to open two pipes (one from GUI->service and one from service->GUI)?
Using WCF you can use duplex named pipes
// Create a contract that can be used as a callback
public interface IMyCallbackService
{
[OperationContract(IsOneWay = true)]
void NotifyClient();
}
// Define your service contract and specify the callback contract
[ServiceContract(CallbackContract = typeof(IMyCallbackService))]
public interface ISimpleService
{
[OperationContract]
string ProcessData();
}
Implement the Service
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class SimpleService : ISimpleService
{
public string ProcessData()
{
// Get a handle to the call back channel
var callback = OperationContext.Current.GetCallbackChannel<IMyCallbackService>();
callback.NotifyClient();
return DateTime.Now.ToString();
}
}
Host the Service
class Server
{
static void Main(string[] args)
{
// Create a service host with an named pipe endpoint
using (var host = new ServiceHost(typeof(SimpleService), new Uri("net.pipe://localhost")))
{
host.AddServiceEndpoint(typeof(ISimpleService), new NetNamedPipeBinding(), "SimpleService");
host.Open();
Console.WriteLine("Simple Service Running...");
Console.ReadLine();
host.Close();
}
}
}
Create the client application, in this example the Client class implements the call back contract.
class Client : IMyCallbackService
{
static void Main(string[] args)
{
new Client().Run();
}
public void Run()
{
// Consume the service
var factory = new DuplexChannelFactory<ISimpleService>(new InstanceContext(this), new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/SimpleService"));
var proxy = factory.CreateChannel();
Console.WriteLine(proxy.ProcessData());
}
public void NotifyClient()
{
Console.WriteLine("Notification from Server");
}
}
Your named pipe stream classes (server or client) have to be constructed with a PipeDirection
of InOut
. You need one NamedPipeServerStream
, probably in your service, which can be shared by an arbitrary number of NamedPipeClientStream
objects. Construct the NamedPipeServerStream
with the name of the pipe and the direction, and the NamedPipeClientStream
with the name of the pipe, the name of the server, and the PipeDirection
, and you should be good to go.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With