2010-03-09 54 views
6

我正在處理傳統RPC實現的客戶端/服務器庫,並且遇到了等待接收RPC請求消息的響應消息時客戶端有時會掛起的問題。事實證明,真正的問題在於我的消息幀代碼(從底層NetworkStream讀取數據時,我沒有正確處理消息邊界),但這也讓我懷疑我用來通過網絡發送數據的代碼,特別是在RPC服務器由於客戶端RPC請求而向客戶端發送大量數據的情況下。Stream.Write是線程安全的嗎?

我的發送代碼使用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調用來阻止流?

回答

8

此類型的任何公共靜態(在Visual Basic中共享)成員都是線程 safe。任何實例成員不是 保證是線程安全的。

Stream Class,所以沒有它不能保證。

+1

我也看到了,但由於該免責聲明適用於BCL中的幾乎每一個類,因此我想知道是否可能存在'Stream'異常,我可能在文檔中的其他地方忽略了它。 – 2010-03-09 07:20:04

+1

很抱歉,但並不是我所知道的。確保你把它交到你自己的手中,以確保這部分代碼是線程安全的。 – 2010-03-09 07:21:17

+1

不需要抱歉;)。我同意在任何情況下添加明確的同步都是安全合理的。我只是好奇它是否已經「內置」到「Stream」中,因爲「線程安全」免責聲明並不打折。有時MSDN往往會含糊不清。 – 2010-03-09 07:27:55

2

它沒有記錄爲原子。我不會假設它是,並且肯定會圍繞自定義鎖定機制包裝這些東西。基本上整個發送方法幾乎要求鎖定。

0

您應該鎖定兩個線程中的寫入程序以確保。作者Afair不是線程安全的。

查看MSDN的「Monitor」和「Mutex」。