首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >.NET中的双工命名管道在读取(异步写入)期间写入时会被卡住

.NET中的双工命名管道在读取(异步写入)期间写入时会被卡住
EN

Stack Overflow用户
提问于 2022-04-04 17:08:13
回答 1查看 247关注 0票数 0

我有一个.NET应用程序,它通过一个NamedPipe从它的父NodeJS应用程序读取消息,然后通过stdout将消息写回来。这很好,代码看起来大致如下所示:

节点:

代码语言:javascript
运行
复制
const { spawn } = require("child_process");
const net = require("net");
const os = require("os");

let proc;
function main() {
    const socket = await setUpNamedPipe();

    proc.stdout.setEncoding("utf-8");
    proc.stdout.on("data", message => {
        message.trimEnd().split(os.EOL).forEach(m => {
          console.log(m);
        })   
    });

    socket.write("message1" + os.EOL);
    socket.write("message2" + os.EOL);
    socket.write("message3" + os.EOL);
    socket.write("message4" + os.EOL);
    socket.write("message5" + os.EOL);
}

function setUpNamedPipe() {
  const pipeName = "MyPipe";
    const pipePath = `\\\\.\\pipe\\${pipeName}`;
    let myResolve;
    const somePromise = new Promise(r =>
    {
        myResolve = r;
    });
    const server = net.createServer((socket) =>
    {
        myResolve(socket);
    });

    server.listen(pipePath, () =>
    {
        proc = spawn("Test.exe", [pipeName]);
    });

    return somePromise;
}

.NET应用程序:

代码语言:javascript
运行
复制
using System.IO.Pipes;

public class Program
{
    public static void ListenForMessages(TextReader reader)
    {
        while (true)
        {
            string message = reader.ReadLine();
            if (message == null)
            {
                return;
            }
            Console.WriteLine(message);
        }
    }

    public static void Main(string[] args)
    {
        string pipeName = args[0];
        using NamedPipeClientStream client = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut); // Just `In` doesn't work for some reason
        client.Connect();
        using TextReader reader = TextReader.Synchronized(new StreamReader(client));

        Task.Factory.StartNew(() => ListenForMessages(reader), TaskCreationOptions.LongRunning).Wait();
    }
}

如果我将其设置为双工命名管道,将proc.stdout.on("data", ...)替换为socket.on("data", ...),并在socket.on("data", ...)应用程序中创建类似于创建TextReaderTextWriter

代码语言:javascript
运行
复制
using TextReader reader = TextReader.Synchronized(new StreamReader(client));

然后使用writer.WriteLine(...); writer.Flush();而不是Console.WriteLine编写任务,我不会从我的.NET应用程序中收到任何消息(除非我等待任务完成)。我是不是错过了一步?

大致类似:

代码语言:javascript
运行
复制
public static void ListenForMessages(NamedPipeClientStream client)
{
    using TextWriter writer = TextWriter.Synchronized(new StreamWriter(client));
    using TextReader reader = TextReader.Synchronized(new StreamReader(client));
    while (true)
    {
        client.WaitForPipeDrain();
        string message = reader.ReadLine();
        if (message == null)
        {
            return;
        }

        Task.Run(() => {
            writer.WriteLine(message);
            writer.Flush();
        }); // only works if I add `.Wait()`
    }
}

public static void Main(string[] args)
{
    string pipeName = args[0];
    using NamedPipeClientStream client = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut);
    client.Connect();

    Task.Factory.StartNew(() => ListenForMessages(client), TaskCreationOptions.LongRunning).Wait();
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-06 20:11:19

我只需将PipeOptions.Asynchronous标志传递给构造函数,如下所示:

代码语言:javascript
运行
复制
new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71741113

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档