2017-10-18 104 views
0

我使用C#(.NET Framework v4.5)爲客戶端和服務器創建新遊戲項目的服務器。在多線程套接字服務器上使用事件

我目前正在使用類似的東西來管理我的球員。

new Thread(() => 
{ 
    connection.ListenAndSend(); 
}).Start(); 

public void ListenAndSend() 
{ 
    while(working) 
    { 
     if(someThingToRead) 
     { 
     //Listening logic here 

     //Here i call my event for dataReceived with the data i just read. 
     } 
     else if (queue.Count > 0) 
     { 
      Send(queue.Dequeue().Data); //Send data from the Queue 
     } 
    } 

使用一個隊列是因爲我不應該訪問來自不同線程的流(它拋出InvalidOperationException異常我覺得),所以我實施的隊列從同一線程發送數據。

我認爲這大多是好的,但即時擔心的事件。

事件被解僱和工作正常,但我還沒有與多個客戶端,以便測試...

  • 是在同一個線程正在執行的事件偵聽器線程?
  • 我可以在多個線程同時修改字段時遇到問題嗎? (我比較有經驗的java例如,我記得一些關於Syncronize接口?)
  • 它現在還沒有完成,但後來它可能會有一些事件最終會調用發送方法,所以添加數據到發送隊列(但這應該不是一個問題吧?)

這個遊戲將永遠不會爲大量的球員(可能介於2至8),如果這件事。

我有沒有看到一些嚴重的問題?

即時通訊使用隊列即時通訊認爲不管什麼線程添加數據,但將我的偵聽停止,而它正在執行事件代碼? (如果它真的在同一個線程上),雖然這不是一個真正的問題,它會同時訪問來自多個線程的字段?

更新:

我可以使所有這一切只與異步/等待?我不能看到如何使這個聽循環,但如果真的有可能請擴大答案。

另外,這answer說相反。

更新2:

現在,我過我的代碼,我知道它的工作的罰款。

正如評論指出,我可以做這個使用異步/少了很多線程等待,但:

在它會更好地使用異步/等待着,而不是線程,請記住我的遊戲服務器應該能夠根據需要獲取儘可能多的cpu /內存,如果可以的話,它的罰款也很高(當然,線程在不工作時調用睡眠)。而且我希望我的服務器儘可能地接近實時。

我也想指出,我第一次開始處理我的邏輯,遊戲地圖的序列化(約60k對象)花了大約600ms(這將是每個客戶端),所以我結束了移動序列化作業到套接字線程。

考慮到這一點,誰認爲這將是更好地使用異步/等待而不是新的線程

PD:我只是在談論我的服務器,遊戲客戶端確實使用異步/等待與溝通服務器。

+0

你在使用'NetworkStream'嗎?因爲你不能從多個線程訪問它 - 只要你沒有兩個線程同時讀取,或者兩個線程同時寫入。 –

+0

您執行'ListenAndSend'方法作爲後臺線程。您的事件處理程序將在同一個線程中執行(並阻止進一步接收),您可以使用https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher(v=vs.110)的.aspx。 –

+0

@ C.Evenhuis是的即時通訊使用NetworkStream和我敢肯定,我從另一個線程調用寫入時得到一個異常(雖然它很可能其他線程調用讀取),但即使我可以應該我? – Nanoc

回答

2

你有2種選擇,醚鎖定變量(不推薦) How to lock a variable used in multiple threads

或使用調度員從另一個線程調用的方法,如果你不使用WPF Using the C# Dispatcher

,你可能需要看看這個鏈接:how do I convert wpf dispatcher to winforms

+0

沒有「來自其他線程的方法」。線程執行,他們不擁有自己的方法。調度程序*需要更新UI控件。所有受支持的.NET版本雖然現在都支持'async/await',所以不需要使用調度程序 –

相關問題