我一直在尝试确定是否可以跨管道客户端的线程共享管道句柄(在窗口上)。我最初的想法是,我不能,因为除非我同步线程,否则数据可能会在服务器上交错显示,从而导致问题。但是我现在想知道PIPE_TYPE_MESSAGE和PIPE_READMODE_MESSAGE的管道是否允许我有一个多线程管道客户端共享一个管道句柄。有没有人对此有明确的答案?
我希望跨客户端线程共享单个管道句柄的原因是为了节省每次我想要发送数据时打开管道的成本。我无法轻松缓存客户端线程的管道句柄,因为我没有创建客户端线程。
我添加了https://msdn.microsoft.com/en-us/library/windows/desktop/aa365605(v=vs.85).aspx的片段,其中描述了管道类型模式。我突出了这部分,让我想知道消息模式是否会完成我想要做的事情。
...
类型模式
管道的类型模式决定了如何将数据写入命名 管。数据可以通过命名管道作为流传输 字节数或消息流。管道服务器指定 调用CreateNamedPipe创建一个实例时的管道类型 命名管道。对于a的所有实例,类型模式必须相同 管。
要创建字节类型管道,请指定PIPE_TYPE_BYTE或使用默认值 值。数据作为字节流写入管道,并且 系统不区分不同的写入字节 写操作。
要创建消息类型管道,请指定PIPE_TYPE_MESSAGE。 系统 将每次写操作中写入的字节视为一个管道 消息单元。系统始终执行写入操作 消息类型的管道就像启用了直写模式一样。
...
谢谢, 尼克
答案 0 :(得分:1)
ReadFile和WriteFile WinAPI函数都是线程安全的。不像我之前写的那样(对此感到抱歉),这种线程安全性并不能保证来自不同线程的并发写入不会被交错。换句话说,不保证首先开始写入其数据的线程将在某个其他线程获得写访问权之前完成。来自MSDN:
虽然单扇区写入是原子的,但除非您使用事务(即创建的句柄是事务处理句柄;例如,使用CreateFileTransacted创建的句柄),否则不保证多扇区写入是原子的。
这表明可以使用事务处理操作进行原子写入,但我对此上下文中的事务并不了解。
要兑换自己,我会尝试为您的问题提出替代解决方案。您可以在客户端中拥有一个单独的 writer 线程,该线程具有管道的独占写入权限。所有其他线程将其消息推送到FIFO队列,而编写器线程读取队列并通过管道发送数据。这比锁定整个写操作更好,因为enqueue / dequeue操作要快得多,并且线程不会长时间被阻塞。
您可以以编写器线程可以等待它的方式实现队列,并且只有在队列中有消息时才会唤醒。否则,编写器线程将有一个繁忙的循环,这是一个讨厌的解决方案。