Stream.Write是否是线程安全的?

时间:2010-03-09 07:09:24

标签: c# multithreading networking c#-2.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(并暗示调用基础Stream的{​​{1}}方法)原子?也就是说,如果发送线程上仍在进行冗长的Write,并且心跳线程启动并发送PING消息,那么该线程是否会阻塞,直到原始Write调用结束,或者我是必须向Write方法添加显式同步,以防止两个Send调用破坏流?

3 个答案:

答案 0 :(得分:9)

  

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

来自Stream Class,所以无法保证。

答案 1 :(得分:2)

没有记录为原子。我不认为它是肯定会将这些东西包裹在自定义锁定机制周围。基本上整个Send方法几乎要求锁定。

答案 2 :(得分:0)

您应该在两个线程中锁定编写器以确保。作者不是线程安全的。

检查MSDN“Monitor”和“Mutex”。