为什么从管道读取会阻塞该过程?

时间:2019-06-14 08:40:47

标签: .net ipc named-pipes

我有两个进程(均为.NET Framework个应用程序),我正在尝试使用Named Pipes进行通信 客户端连接到管道,但是当它尝试ReadAsync服务器发送的消息时,即使服务器已经发送了消息,它也开始独立地等待

让我惊讶的是,如果我关闭Server应用程序,Client最终会继续到下一行代码(在ReadAsync行之后),已读取 0 个字节。

WriteAsync-装入有效负载后,我必须在服务器上进行任何操作吗?我需要冲洗或其他任何东西吗?

服务器

static async Task Main(string[] args) {

         var server = new NamedPipeServerStream(
             "somePipe",
              PipeDirection.InOut, 
              2, 
              PipeTransmissionMode.Message
              );

         await server.WaitForConnectionAsync();

         using (StreamReader reader = new StreamReader(server)) {
              using (StreamWriter writer = new StreamWriter(server)) {

                 await writer.WriteAsync("Hello from server"); 

                 char[] buffer = new char[20];
                 var read = await reader.ReadAsync(buffer, 0, buffer.Length);
                }
         }
}

客户

 static async Task Main() {

    NamedPipeClientStream client = new NamedPipeClientStream(
             ".",
             "somePipe",
             PipeDirection.InOut,
             PipeOptions.Asynchronous);

    await client.ConnectAsync();

    try {
    using (StreamReader reader = new StreamReader(client)) {
        using (StreamWriter writer = new StreamWriter(client)) {

          var buffer = new char[20];
          int readChars = await reader.ReadAsync(buffer, 0,buffer.Length); //starts waiting indifinetly , until i close the Server

          await writer.WriteAsync("From Client");

        }
     }
     } catch (Exception ex) {

       throw;
     }
}

更新 似乎直接使用NamedPipeServerStream代替服务器端的StreamWriter可以使客户端获得数据!

服务器更改

byte[] data=Encoding.UTF8.GetBytes("Hello from server");
server.WriteAsync(data,0,data.Length);

PS 但是,再次使用serverReadAsync会阻塞服务器。因此,将NamedPipeServerStreamClientStream包装到StreamReaderStreamWriter中时会出现问题。

1 个答案:

答案 0 :(得分:1)

此阻止/锁定问题是由异步/等待语法糖秘密生成的代码引起的。 如果不添加ConfigureAwait(false),则编译器会生成对UI应用程序很酷的东西(UI是一个通用术语,可能是ASP.NET-不是core-,WPF,Winforms等),但是可以否则会致命。

有关此事的很多写道:

Don't Block on Async Code

引用:

  

有两种最佳做法可以避免这种情况:

     
      
  • 在“库”异步方法中,无论何时何地都可以使用ConfigureAwait(false)   可能。
  •   
  • 不要阻止任务;一直使用异步。
  •   

Parallel Computing - It's All About the SynchronizationContext

Best practice to call ConfigureAwait for all server-side code

Should I call ConfigureAwait(false) on every awaited operation

因此,最简单的解决方案是在未知的用户界面代码中添加ConfigureAwait(false) 无处不在,或使用async 无处不在 em>(永远不会阻塞整个代码中的任何任务,甚至在任何地方,包括您不拥有的代码中)。

恕我直言,这太荒谬了……我个人使用了一个Visual Studio扩展,如果我忘记将其添加到每个async调用之后,我会大吼大叫:-)

请注意,有一些替代方法,例如: An alternative to ConfigureAwait(false) everywhere