NamedPipeClientStream.Write 块

Posted

技术标签:

【中文标题】NamedPipeClientStream.Write 块【英文标题】:NamedPipeClientStream.Write blocks 【发布时间】:2021-03-23 14:51:05 【问题描述】:

我只是想了解 C# 中的管道。我有一个简单的 LinqPad 脚本:

void Main() =>  Program.Main(null);

// You can define other methods, fields, classes and namespaces here
    class Program
    
        public static void Main(string[] args)
        
            StartServer();
            Task.Delay(1000).Wait();

            //Client
            var client = new NamedPipeClientStream("PipesOfPiece");
            client.Connect();

            while (true)
            
                string input = Guid.NewGuid().ToString();
                if (String.IsNullOrEmpty(input)) break;
                
                var someBuffer = new byte[4];
                client.Write(someBuffer, 0, someBuffer.Length);
                "Client 1st Write".Dump();
                
                client.Write(someBuffer, 0, someBuffer.Length);
                "Client 2nd Write".Dump();
                
                client.Read(someBuffer, 0, someBuffer.Length);
                "Client 1st Read".Dump();
            
        

        static void StartServer()
        
            Task.Factory.StartNew(() =>
            
                var server = new NamedPipeServerStream("PipesOfPiece");
                server.WaitForConnection();
                var someBuffer = new byte[4];
                while (true)
                
                    server.Read(someBuffer, 0, someBuffer.Length);
                    "Server 1st Read".Dump();
                    server.Write(someBuffer, 0, someBuffer.Length);
                    "Server 1st Write".Dump();
                
            );
        
    

如果我运行上面的代码,我会得到以下输出:

Client 1st Write
Server 1st Read

所以对client.Write 的第二次调用将永远阻塞。有人可以解释一下为什么第二次调用 write(在同一个线程中)会导致管道永远阻塞吗?

谢谢

【问题讨论】:

什么是Dump() Stream.Write 是同步方法,即阻塞。如果您想避免阻塞,请使用WriteAsync。您必须将签名更改为static async Task Main 【参考方案1】:

其根本原因是根据synchrozniation context 和线程切换阻塞问题。 像这个家伙那样做:

public static async Task Main(string[] args)

        StartServer();
        await Task.Delay(1000);

        //Client
        var client = new NamedPipeClientStream("PipesOfPiece");
        await client.ConnectAsync();

        while (true)
        
            string input = Guid.NewGuid().ToString();
            if (String.IsNullOrEmpty(input)) break;

            var someBuffer = new byte[4];
            await client.WriteAsync(someBuffer, 0, someBuffer.Length);
            Console.WriteLine("Client 1st Write");

            await client.WriteAsync(someBuffer, 0, someBuffer.Length);
            Console.WriteLine("Client 2nd Write");

            await client.ReadAsync(someBuffer, 0, someBuffer.Length);
            Console.WriteLine("Client 1st Read");

            //await Task.Delay(100);

        
    

    static void StartServer()
    
        Task.Factory.StartNew(async () =>
        
            var server = new NamedPipeServerStream("PipesOfPiece");
            await server.WaitForConnectionAsync();

            var someBuffer = new byte[4];
            while (true)
            
                await server.ReadAsync(someBuffer, 0, someBuffer.Length);
                Console.WriteLine("Server 1st Read");
                await server.WriteAsync(someBuffer, 0, someBuffer.Length);
                Console.WriteLine("Server 1st Write");
            
        );
    

【讨论】:

我得到了一些与同步一样的输出。例如Client 1st Write Server 1st Read。所以第二个WriteAsync 似乎陷入了僵局。 亲爱的 Moerwald 很遗憾我听不懂你在说什么,请澄清你的话

以上是关于NamedPipeClientStream.Write 块的主要内容,如果未能解决你的问题,请参考以下文章