我正在为传统的RPC实现开发客户端/服务器库,并且在等待接收到RPC请求消息的响应消息时,客户端有时会挂起这些问题。事实证明,真正的问题出在我的消息框架代码中(当我从底层NetworkStream
读取数据时,我没有正确处理消息边界),但它也让我怀疑我用来发送数据的代码网络,特别是在RPC服务器因客户端RPC请求而向客户端发送大量数据的情况下。
我的发送代码使用BinaryWriter
向基础NetworkStream
写入完整的“消息”。 RPC协议还实现了心跳算法,其中RPC服务器每15秒发送一次PING消息。 ping是由一个单独的线程发出的,因此,至少在理论上,当服务器处于将大响应流回客户端时,可以发送ping。
假设我有一个Send
方法,其中stream
是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();
}
所以我的问题是,调用bw.Write
(并暗示调用基础Stream
的{{1}}方法)原子?也就是说,如果发送线程上仍在进行冗长的Write
,并且心跳线程启动并发送PING消息,那么该线程是否会阻塞,直到原始Write
调用结束,或者我是必须向Write
方法添加显式同步,以防止两个Send
调用破坏流?
答案 0 :(得分:9)
任何公共静态(在Visual中共享) 基本)这种类型的成员是线程 安全。任何实例成员都不是 保证是线程安全的。
来自Stream Class,所以否无法保证。
答案 1 :(得分:2)
没有记录为原子。我不认为它是肯定会将这些东西包裹在自定义锁定机制周围。基本上整个Send方法几乎要求锁定。
答案 2 :(得分:0)
您应该在两个线程中锁定编写器以确保。作者不是线程安全的。
检查MSDN“Monitor”和“Mutex”。