For bidirectional data exchange between my C# applications I use named pipe. App-1 is the pipe server, App-2 is the client. When a button is clicked in App-1 the pipe_server method is executed and and App-1,as server is waiting for connection from App-2. After clicking the button for the first time, everything works as expected. App-2 connects and sends data to App-1.
After each data transfer I am disposing the pipe server.I want that for every new button click a new pipe stream is generated, and the data transfer runs from beginnng as before. But after second click of the button I always get "System.ObjectDisposedException: Cannot access a closed pipe". on the server side. I think I make something wrong when disposing the pipestream on the server side.
Server side (App-1)
public string test = "";
public StreamReader sr ;
public StreamWriter sw ;
public NamedPipeServerStream pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous, 20, 20);
public void pipe_server // executed on button click
{
CancellationTokenSource source = new CancellationTokenSource();
server_named_pipe(source.Token);
}
protected async Task server_named_pipe(CancellationToken stoppingToken)
{
PipeSecurity ps = new PipeSecurity();
System.Security.Principal.SecurityIdentifier sid = new System.Security.Principal.SecurityIdentifier(System.Security.Principal.WellKnownSidType.WorldSid, null);
PipeAccessRule par = new PipeAccessRule(sid, PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow);
ps.AddAccessRule(par);
sr = new StreamReader(pipeServer);
sw = new StreamWriter(pipeServer);
try
{
var asyncResult = pipeServer.BeginWaitForConnection(PipeConnected, this);
if (asyncResult.AsyncWaitHandle.WaitOne(5000))
{
pipeServer.EndWaitForConnection(asyncResult);
// ...
}
}
catch (Exception ex)
{
//throw ex;
pipeServer.WaitForPipeDrain();
if (pipeServer.IsConnected)
{
pipeServer.Disconnect();
}
}
finally
{
if (sw != null) sw.Dispose();
if (sr != null) sr.Dispose();
pipeServer.Dispose();
}
}
}
public void PipeConnected(IAsyncResult e)
{
sw.WriteLine("Waiting");
sw.Flush();
pipeServer.WaitForPipeDrain();
test = sr.ReadLine();
using (StreamWriter sw2 = File.AppendText(CommonClass.error_path))
{
sw2.WriteLine("Named_Pipe_message: " + " " + test + Convert.ToString(DateTime.Now) + " ");
}
}
Than you should recreate the server. You can't (usually) use disposed resources. You need to recreate the
NamedPipeServerStreamafter disposal (as you do withStreamReader/StreamWriter). For example:Personally you would remove the
pipeServer,srandsrfields and moved all the handling inside theserver_named_pipemethod.