2013-12-15 83 views
0

我正在創建一個客戶端 - 服務器結構,其中服務器爲每個客戶端都有一個線程。 該特定線程僅發送和接收數據。在服務器的主線程中,我想讀取clientthread收到的輸入。但是在mainthread正在閱讀的同時,這個輸入可能會被clientthread修改。我會如何防止這種情況?我讀過鎖,但不知道如何以這種方式實現它們。鎖定資源或不在多線程服務器

我的問題的第二部分是:clientthread是一個不斷從網絡流讀取的循環,因此阻塞該線程,直到它可以讀取某些內容。但是,我可以從我的主線程調用一個函數(該函數會通過該網絡流發送一些東西),現有的clientthread(即循環)必須執行?

對不起,我現在不能給任何代碼,但我認爲這足夠清楚了嗎?

+1

恐怕這個描述太含糊了。代碼會更好。我不明白你會如何得到更多的一般性建議。 – usr

+0

其實它只是一般的建議,我需要:) –

+1

你必須使用鎖定來防止事故。如果你有一個不重要的客戶端連接數,這將對吞吐量產生非常不利的影響,所有這些線程都會在鎖上爭奪。你解決這個問題是不要這樣做,最好的一般建議。 –

回答

1

聽起來像生產者 - 消費者設計可能很適合你的問題。一般而言,客戶端線程會將接收到的數據放入(線程安全)隊列中,之後不會對其進行修改 - 任何到達的新數據都會進入隊列中的新插槽。然後,主線程可以等待任何隊列中的新數據並在其到達時進行處理。主線程可以定期檢查所有隊列,或者(更好)在數據放入隊列時接收某種通知,以便在沒有任何事情發生時可以休眠,並且不會佔用CPU時間。

既然你問鎖:這是一個基本的基於鎖的實現作爲替代隊列,也許,這將有助於你明白一個道理

class IncomingClientData 
{ 
    private List<byte> m_incomingData = new List<byte>(); 
    private readonly object m_lock = new object(); 

    public void Append(IEnumerable<byte> data) 
    { 
     lock(m_lock) 
     { 
      m_incomingData.AddRange(data); 
     } 
    } 

    public List<byte> ReadAndClear() 
    { 
     lock(m_lock) 
     { 
      List<byte> result = m_incomingData; 
      m_incomingData = new List<byte>(); 
      return result; 
     } 
    } 
} 

在這個例子中,客戶端線程將調用Append與他們收到的數據以及主線程可以通過調用ReadAndClear收集自上次檢查以來收到的所有收到的數據。

這是線程安全的通過鎖定在這兩個函數的所有代碼上m_lock,這只是一個普通的簡單的對象 - 你可以在C#中的任何物體鎖定,但我相信這可能會造成混淆,實際上導致微妙如果不小心使用了錯誤,所以我幾乎總是使用專用對象來鎖定。一次只有一個線程可以鎖定對象,因此這些函數的代碼一次只能在一個線程中運行。例如,如果您的主線程在客戶線程仍然忙於將數據追加到列表中時調用ReadAndClear,那麼主線程將等待客戶線程離開Append函數。

這不是要求爲此創建一個新類,但它可以防止意外,因爲我們可以小心控制共享狀態如何被訪問。例如,我們知道在ReadAndClear()中返回內部列表是安全的,因爲當時不能有其他參考。

現在爲您的第二個問題:只是簡單地調用一個方法將永遠不會導致該方法在不同的線程上運行,無論該方法在哪個類中。Invoke是WinForms UI線程的一個特殊功能,您如果你想在你的工作線程中使用Invoke,你必須自己實現這個功能。在內部,Invoke的工作方式是將要運行的代碼放入應該在UI線程上運行的所有事物的隊列中,包括UI事件。 UI線程本身基本上是一個循環,它總是從該隊列中提取下一項工作,然後執行該工作,然後從隊列中獲取下一項,等等。這也是爲什麼你不應該在事件處理程序中長時間工作 - 只要UI線程忙於運行你的代碼,它將無法處理其隊列中的下一個項目,所以你會支持所有發生的其他工作項目/事件。

如果你想要你的客戶端線程運行某個功能,你必須實際提供代碼 - 例如讓客戶端線程檢查某個隊列中主線程的命令。

+0

感謝您對我的抽象問題的完整回答!現在我想知道該怎麼做,再次感謝。但是對於第二部分,例如,我將無法與委託人一起完成這項工作。 –

+0

你可以使用代表,但有趣的問題是你會*與他們做什麼。 – Medo42

+0

我編輯了我的問題的第二部分。這可能嗎?我將如何實現這一目標?在此先感謝 –