为什么从管道读取会阻塞该过程? [英] Why does reading from pipe block the process?

查看:201
本文介绍了为什么从管道读取会阻塞该过程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have two processes ( both .NET Framework applications) and i am trying to communicate using Named Pipes The client connects to the pipe , but when it tries to ReadAsync the message sent by the server, it starts waiting indifinetly , even though the server has already sent a message !!

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

What surprises me is that if i close the Server app the Client finally continues to the next line of code (after the ReadAsync line), having read 0 bytes.

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

Is there anything i must to on the server after WriteAsync-ing the payload? Do i need to flush or anything ?

服务器

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可以使客户端获取数据!

Update It seems using the NamedPipeServerStream directly to write instead of the StreamWriter on the server side makes the client get the data !

服务器更改

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

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

P.S However using again the server to ReadAsync blocks the server.So there is a problem when wrapping the NamedPipeServerStream and ClientStream into StreamReader and StreamWriter.

推荐答案

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

This blocking/lock issue is caused by the code that's generated undercovers by the async/await syntactic sugar. If you don't add ConfigureAwait(false), the compiler generates something that's cool for a UI application (UI is a general term, could be ASP.NET - not core - , WPF, Winforms, etc.), but that can be deadly otherwise.

关于此事,很多写道:

不要阻止异步代码

引用:

有两种最佳实践可以避免这种情况:

There are two best practices [...] that avoid this situation:

  • 在库"异步方法中,无论何时何地都可以使用ConfigureAwait(false) 可能.
  • 不要阻止任务;一直使用异步.
  • In your "library" async methods, use ConfigureAwait(false) wherever possible.
  • Don’t block on Tasks; use async all the way down.

并行计算-一切都与SynchronizationContext有关

为所有服务器-附带代码

我应该在每个等待的操作上调用ConfigureAwait(false)

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

So, the simplest solution is to add ConfigureAwait(false) everywhere in your code that is not known to run in the UI, or use async everywhere (never block on any task ever in your whole code, really everywhere, including in code you don't own).

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

IMHO, this is ridiculous... I personally use a Visual Studio extension that yells at me, if I forget to add it behind every async call :-)

请注意,有一些替代方法,例如: ConfigureAwait的替代方法(false)到处都是

Note there are some alternatives, for example: An alternative to ConfigureAwait(false) everywhere

这篇关于为什么从管道读取会阻塞该过程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆