当前位置: 首页 > 知识库问答 >
问题:

NamedPipeClientStream.Write块

刘元青
2023-03-14

我只是想理解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(在同一线程中)会导致管道阻塞吗?

THX

共有1个答案

伯君浩
2023-03-14

其根本原因是根据同步化上下文和线程切换阻塞问题。像这样做伙计:

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");
            }
        });
    }
 类似资料:
  • 问题内容: 我想知道在Python应用程序中导入包的首选方法。我有一个这样的包结构: project.app1.views进口project.app1.models和project.app2.models。我想到有两种方法可以做到这一点。 绝对进口: 或具有明确的相对导入,如在Python 2.5中使用PEP 328引入的那样: 什么是最pythonic的方式做到这一点? 问题答案: 绝对进口。从

  • 问题内容: 我们目前正在编写一个应用程序,该应用程序分为多个项目/模块。例如,让我们采用以下模块: myApp-DAO myApp-jabber 每个模块都有其自己的Spring上下文xml文件。对于DAO模块,我有一个PropertyPlaceholderConfigurer,它读取带有必需的数据库连接参数的属性文件。在jabber模块中,我还有一个用于jabber连接属性的PropertyPl

  • 问题内容: 我已经开始学习线程同步。 同步方法: 同步块: 什么时候应该使用方法和块? 为什么块比方法更好? 问题答案: 这不是更好的问题,只是有所不同。 同步方法时,实际上是在与对象本身进行同步。对于静态方法,您正在同步到对象的类。因此,以下两段代码以相同的方式执行: 就像您写的一样。 如果要控制到特定对象的同步,或者只想将方法的 一部分 同步到该对象,则指定一个块。如果在方法声明上使用关键字,

  • 问题内容: 我想知道使用像这样的构造是否可靠: 我是否有可能因为初始化块将在初始化块之前执行? (关于我为什么不在上层init的末尾进行初始化。块:只是味道问题;如果所描述的构造不可靠,我将这样做) 问题答案: 是的,保证静态初始化程序块按文本顺序执行。 从JLS,第12.4.1节: 目的是类或接口类型具有一组初始化器,这些初始化器将其置于一致状态,并且该状态是其他类观察到的第一个状态。 静态初始

  • 问题内容: 我知道如何按字节读取文件,但是找不到如何按字节读取文件的示例。我有一个字节数组,我想读取512bytes的文件并通过套接字发送它们。 我尝试读取文件的总字节,然后减去512字节,直到得到小于512字节的块,并发出EOF和传输结束的信号。 我正在尝试实现TFTP,其中以512字节块发送数据。 无论如何,我们将为一个例子而感激。 问题答案: 您…一次读取512个字节。

  • 问题内容: 不得不与Guice打交道,我想知道我应该如何处理模块方面的依赖关系。 在Guice中,每个模块都是由实例提供的。因此,如果我有一个需要某种服务的模块,它将创建一个向该服务添加绑定的模块并进行安装(binder.install(module))。 现在,我有两个独立的模块,完全可以独立使用,并且都安装了相同的数据库模块。 单独使用两个模块都不会出现问题,但是如果两个模块在同一应用程序中使