Stream.Write 是线程安全的吗?

发布于 2024-08-24 13:54:29 字数 1287 浏览 4 评论 0原文

我正在为旧版 RPC 实现开发客户端/服务器库,但遇到了客户端在等待接收 RPC 请求消息的响应消息时有时会挂起的问题。事实证明,真正的问题出在我的消息框架代码中(当从底层 NetworkStream 读取数据时,我没有正确处理消息边界),但这也让我对我用来实现消息框架的代码产生了怀疑。通过网络发送数据,特别是在 RPC 服务器根据客户端 RPC 请求向客户端发送大量数据的情况下。

我的发送代码使用 BinaryWriter 将完整的“消息”写入底层 NetworkStream。 RPC 协议还实现了心跳算法,其中 RPC 服务器每 15 秒发送一次 PING 消息。 ping 是由单独的线程发出的,因此,至少在理论上,可以在服务器将大量响应流式传输回客户端时发送 ping。

假设我有一个 Send 方法,如下所示,其中 streamNetworkStream

public void Send(Message message)
{
   //Write the message to a temporary stream so we can send it all-at-once
   MemoryStream tempStream = new MemoryStream();
   message.WriteToStream(tempStream);

   //Write the serialized message to the stream.
   //The BinaryWriter is a little redundant in this 
   //simplified example, but here because
   //the production code uses it.
   byte[] data = tempStream.ToArray();
   BinaryWriter bw = new BinaryWriter(stream);
   bw.Write(data, 0, data.Length);
   bw.Flush();
}

所以我的问题是,是对 的调用bw.Write (并且隐含对底层 StreamWrite 方法的调用)是原子的吗?也就是说,如果发送线程上仍在进行冗长的Write,并且心跳线程启动并发送 PING 消息,则该线程是否会阻塞,直到原始Write调用完成,或者我是否必须向 Send 方法添加显式同步,以防止两个 Send 调用破坏流?

I'm working on a client/server library for a legacy RPC implementation and was running into issues where the client would sometimes hang when waiting to a receive a response message to an RPC request message. It turns out the real problem was in my message framing code (I wasn't handling message boundaries correctly when reading data off the underlying NetworkStream), but it also made me suspicious of the code I was using to send data across the network, specifically in the case where the RPC server sends a large amount of data to a client as the result of a client RPC request.

My send code uses a BinaryWriter to write a complete "message" to the underlying NetworkStream. The RPC protocol also implements a heartbeat algorithm, where the RPC server sends out PING messages every 15 seconds. The pings are sent out by a separate thread, so, at least in theory, a ping can be sent while the server is in the middle of streaming a large response back to a client.

Suppose I have a Send method as follows, where stream is a NetworkStream:

public void Send(Message message)
{
   //Write the message to a temporary stream so we can send it all-at-once
   MemoryStream tempStream = new MemoryStream();
   message.WriteToStream(tempStream);

   //Write the serialized message to the stream.
   //The BinaryWriter is a little redundant in this 
   //simplified example, but here because
   //the production code uses it.
   byte[] data = tempStream.ToArray();
   BinaryWriter bw = new BinaryWriter(stream);
   bw.Write(data, 0, data.Length);
   bw.Flush();
}

So the question I have is, is the call to bw.Write (and by implication the call to the underlying Stream's Write method) atomic? That is, if a lengthy Write is still in progress on the sending thread, and the heartbeat thread kicks in and sends a PING message, will that thread block until the original Write call finishes, or do I have to add explicit synchronization to the Send method to prevent the two Send calls from clobbering the stream?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

疯到世界奔溃 2024-08-31 13:54:29

任何公共静态(在视觉中共享
基本)该类型的成员是线程
安全的。任何实例成员都不是
保证线程安全。

来自 Stream 类,所以

Any public static (Shared in Visual
Basic) members of this type are thread
safe. Any instance members are not
guaranteed to be thread safe.

From Stream Class, so no it is not guaranteed.

烟酉 2024-08-31 13:54:29

它没有记录为原子的。我不会假设它是,并且肯定会将这些东西包裹在自定义锁定机制中。基本上整个 Send 方法几乎都需要锁。

It is not documented as atomic. I would not assume it is and definitely would wrap that stuff around a custom locking mechanism. Basically the whole Send method pretty much asks for a lock.

梦里°也失望 2024-08-31 13:54:29

为了确定,您应该将编写器锁定在两个线程中。公平地说,作者不是线程安全的。

检查 MSDN 中的“Monitor”和“Mutex”。

You should lock the writer in both threads to be sure. Afair the writer is not thread safe.

Check MSDN for "Monitor" and "Mutex".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文