2016-06-30 75 views
1

我一直在閱讀關於Threadpool.QueueUserWorkItem(我一直在使用的),Task.RunTask.Factory.StartNew,我仍然不清楚什麼是正確的選項。看來,因爲我的工作沒有CPU的約束,我可能不應該使用Task.Run確定如何在網絡客戶端連接時正確排隊工作

我有我自己的線程運行等待連接:

Thread listenThread = new Thread(() => ListenForConnection()); 
listenThread.Name = "lThread"; 
listenThread.IsBackground = true; 
listenThread.Start(); 

而且裏面,我簡單地做:

tlist = new TcpListener(IPAddress.Parse(ip.ToString()), 27275); 
tlist.Start(); 

while (isRunning) { 
    try { 
      var client = await tlist.AcceptTcpClientAsync(); 
      ThreadPool.QueueUserWorkItem(HandleClient, client); 
    } 
    catch (Exception) { } 
} 

HandleClient解析客戶端發送的消息,並且創建一個簡單類的實例,或者在客戶端已經存在的情況下更新現有的實例,存儲對連接的引用並更新一些UI元素。

ThreadPool.QueueUserWorkItem這裏的首選方法還是我的方式?

編輯:只是要注意,在HandleClient功能通常需要MS 5和30之間,所以不是很繁重的工作

+0

線程和線程池有點舊了。現代的是Task.Fastory.StartNew和Task.Run。兩者都是具有更好功能的ThreadPool。 –

回答

1

QueueUserWorkItemStartNewRun更或更少等價。我會選Task.Run,因爲它是最現代的方式。

你完成的方式完全沒問題。您選擇了一個同步HandleClient實現,它強制您在單獨的線程上處理連接。請注意,在許多併發連接的情況下,這會消耗很多資源。如果你對這種情況不感興趣,這不是問題。否則,這是一個破壞者。

如果您使HandleClient真正異步且無阻塞,則不需要將該調用推送到線程池。我的建議仍然是這樣做,因爲它的缺點很小,它可以保護您免受該方法過長的同步初始部分的影響。

catch (Exception) { }這個我不明白。這可能會隱藏錯誤。另外,如果最可能接受的錯誤是永久性錯誤。這種錯誤處理會將循環變成佔用一個CPU代碼100%的繁忙循環。將捕獲物移到循環外部。

+0

此應用程序如何工作的性質意味着在任何給定的時間只有一個人可以與其進行物理交互,但可能有x個(最多15個)客戶端隨時連接並等待,因此_many_併發連接不是太很多問題。我也在'HandleClient'中做一些UI工作,目前使用'Dispatcher.Invoke',這可能不是最好的方法?你當然是對的,我會在那裏添加更多特定的錯誤處理,並提醒用戶注意網絡問題。 – sosil

+0

是的,15並不多。 UI非常有利於異步IO並等待。非常高效。我覺得讓網絡層瞭解用戶界面有點骯髒。但是既然這已經是你的方法,不要考慮使用Task.Run並在HancleClient中使用await。您將能夠刪除所有Dispatcher.Invoke調用,並且仍然具有響應式用戶界面。 – usr

+0

另一種方法是不做任何改變,並使用你所擁有的,因爲它沒問題。 – usr

0

我會這樣說:

var tcpListener = new TcpListener(IPAddress.Any, 80); 
tcpListener.Start(); 
while (true) 
{ 
    var tcpClient = tcpListener.AcceptTcpClient(); 
    Task.Factory.StartNew(() => 
    { 
    // Do whatever you like with your TcpClient 
    }); 
} 
相關問題