- Notifications
You must be signed in to change notification settings - Fork29
Open
Description
在 Linux 下的 UOS 系统里面进行测试,如以下代码
varpeer=awaitipcProvider.GetAndConnectToPeerAsync(args[0]);peer.MessageReceived+=(sender,messageArgs)=>{Console.WriteLine($"[{Environment.ProcessId}] 收到{peer.PeerName} 的回复消息:{Encoding.UTF8.GetString(messageArgs.Message.Body.AsSpan())}");};awaitpeer.NotifyAsync(newIpcMessage("Hello",Encoding.UTF8.GetBytes($"Hello,进程号是{Environment.ProcessId} 发送过来消息")));Console.WriteLine($"[{Environment.ProcessId}] 完成发送消息");Console.Read();
那么以上的 MessageReceived 事件将不会被触发,且是因为底层的管道读取无法返回。一旦使用 Task.Run 包括起来,如以下代码,即可正常收到消息
Task.Run(async()=>{varpeer=awaitipcProvider.GetAndConnectToPeerAsync(args[0]);peer.MessageReceived+=(sender,messageArgs)=>{Console.WriteLine($"[{Environment.ProcessId}] 收到{peer.PeerName} 的回复消息:{Encoding.UTF8.GetString(messageArgs.Message.Body.AsSpan())}");};awaitpeer.NotifyAsync(newIpcMessage("Hello",Encoding.UTF8.GetBytes($"Hello,进程号是{Environment.ProcessId} 发送过来消息")));Console.WriteLine($"[{Environment.ProcessId}] 完成发送消息");});Console.Read();
如果给 Task.Run 加上 await 如以下代码,那将无法收到回复,依然是管道读取没有返回,可参考91043ee 的更改
awaitTask.Run(async()=>{varpeer=awaitipcProvider.GetAndConnectToPeerAsync(args[0]);peer.MessageReceived+=(sender,messageArgs)=>{Console.WriteLine($"[{Environment.ProcessId}] 收到{peer.PeerName} 的回复消息:{Encoding.UTF8.GetString(messageArgs.Message.Body.AsSpan())}");};awaitpeer.NotifyAsync(newIpcMessage("Hello",Encoding.UTF8.GetBytes($"Hello,进程号是{Environment.ProcessId} 发送过来消息")));Console.WriteLine($"[{Environment.ProcessId}] 完成发送消息");});Console.Read();
以上代码情况可以排除 Task Main 导致的问题,因为一旦将 Console.Read 换掉,那就可以正常读取到管道里面的消息,管道可以返回,如8d27486 代码更改
awaitTask.Run(async()=>{varpeer=awaitipcProvider.GetAndConnectToPeerAsync(args[0]);peer.MessageReceived+=(sender,messageArgs)=>{Console.WriteLine($"[{Environment.ProcessId}] 收到{peer.PeerName} 的回复消息:{Encoding.UTF8.GetString(messageArgs.Message.Body.AsSpan())}");};awaitpeer.NotifyAsync(newIpcMessage("Hello",Encoding.UTF8.GetBytes($"Hello,进程号是{Environment.ProcessId} 发送过来消息")));Console.WriteLine($"[{Environment.ProcessId}] 完成发送消息");});for(inti=0;i<int.MaxValue;i++){awaitTask.Delay(TimeSpan.FromSeconds(1));}
以上问题的简单复现代码:
internalclassProgram{privatestaticasyncTaskMain(string[]args){varipcProvider=newIpcProvider();ipcProvider.StartServer();if(args.Length==0){varcurrentName=ipcProvider.IpcContext.PipeName;// 将当前的进程的 Name 传递给另一个进程,用来达成通讯varmainModuleFileName=Process.GetCurrentProcess().MainModule.FileName;Console.WriteLine($"[{Environment.ProcessId}] 准备启动{mainModuleFileName} 参数:{currentName}");Process.Start(mainModuleFileName,currentName);}else{// 这是被启动的进程,主动连接发送消息Console.WriteLine($"[{Environment.ProcessId}] 开始连接对方进程");varpeer=awaitipcProvider.GetAndConnectToPeerAsync(args[0]);peer.MessageReceived+=(sender,messageArgs)=>{Console.WriteLine($"[{Environment.ProcessId}] 收到{peer.PeerName} 的回复消息:{Encoding.UTF8.GetString(messageArgs.Message.Body.AsSpan())}");};awaitpeer.NotifyAsync(newIpcMessage("Hello",Encoding.UTF8.GetBytes($"Hello,进程号是{Environment.ProcessId} 发送过来消息")));Console.WriteLine($"[{Environment.ProcessId}] 完成发送消息");}ipcProvider.PeerConnected+=(sender,connectedArgs)=>{Console.WriteLine($"[{Environment.ProcessId}] 收到{connectedArgs.Peer.PeerName} 的连接");connectedArgs.Peer.MessageReceived+=async(o,messageArgs)=>{Console.WriteLine($"[{Environment.ProcessId}] 收到{messageArgs.PeerName} 的消息:{Encoding.UTF8.GetString(messageArgs.Message.Body.AsSpan())}");awaitTask.Delay(TimeSpan.FromSeconds(1));// 反向发送消息给对方Console.WriteLine($"[{Environment.ProcessId}] 向{connectedArgs.Peer.PeerName} 回复消息");awaitconnectedArgs.Peer.NotifyAsync(newIpcMessage("回复",Encoding.UTF8.GetBytes($"收到你的消息")));Console.WriteLine($"[{Environment.ProcessId}] 完成向{connectedArgs.Peer.PeerName} 回复消息");};};Console.WriteLine($"[{Environment.ProcessId}] 等待退出");Console.Read();Console.WriteLine($"[{Environment.ProcessId}] 进程准备退出");}}
以上代码在 Windows 上正常,在 Linux 的 UOS 系统无法收到回复消息,也就是peer.MessageReceived
对应的事件没有触发,调试可以看到管道没有读取返回
详细的各个测试步骤请看#140
可能是 Linux 的 Console.Read 投毒
Metadata
Metadata
Assignees
Labels
No labels