我有两个进程(均为.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
但是,再次使用server
至ReadAsync
会阻塞服务器。因此,将NamedPipeServerStream
和ClientStream
包装到StreamReader
和StreamWriter
中时会出现问题。
答案 0 :(得分:1)
此阻止/锁定问题是由异步/等待语法糖秘密生成的代码引起的。
如果不添加ConfigureAwait(false)
,则编译器会生成对UI应用程序很酷的东西(UI是一个通用术语,可能是ASP.NET-不是core-,WPF,Winforms等),但是可以否则会致命。
有关此事的很多写道:
引用:
有两种最佳做法可以避免这种情况:
- 在“库”异步方法中,无论何时何地都可以使用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