2014-10-01 151 views
0

我有一個服務器應用程序正在偵聽System.Net.Sockets.Socket。它阻止Socket.Accept(),捆綁線程。什麼是放棄線程控制的好方法,但是會將計算結果傳遞給調用客戶端?如何避免在等待請求時阻塞.NET線程

服務器代碼,有些清理,看起來是這樣的:

void ManeLupe(Socket socket) 
{ 
    for (;;) 
    { 
     Socket client = null; 
     NetworkStream stm = null; 
     try 
     { 
      client = socket.Accept();    // Blocks thread 
      stm = new NetworkStream(client); 
      var response = ProcessRequest(stm); // this could take a while 
      WriteResponse(response, stm); 
     } 
     catch (Exception ex) 
     { 
      LogError(client, ex); 
     } 
     finally 
     { 
      if (stm != null) stm.Dispose(); 
      if (client != null) client.Dispose(); 
     } 
    } 
} 

我的約束,目前是該代碼必須在.NET Framework 3.5的運行,所以我不能把優勢新的Task<>async善良。坦率地說,我對通常的異步編程比較陌生,我懷疑它會成爲這個查詢的答案。

回答

2

套接字提供Accept的異步變體,稱爲BeginAccept,這就是您所追求的。

BeginAccept是Accept的APM實現,它爲每個操作提供了一對方法。在這種情況下,您將使用BeginAcceptEndAccept

正如在@CoryNelson的評論中指出的那樣,您也可以考慮使用AcceptAsync。這取決於你選擇哪一個。

+1

'AcceptAsync'也能發揮作用。 – 2014-10-01 17:56:11

+0

@CoryNelson是的,沒錯。我個人不喜歡那個事件(EAP)模型。我會將其添加到我的答案中,謝謝。 – 2014-10-01 17:59:48

+0

的確,取決於用途。對於perf,AcceptAsync是低級的。當然,APM在可用性方面並不是很好。 – 2014-10-01 18:00:47

0

您可以使用委託異步調用方法,該委託提供調用begininvoke的選項,可以通過參考asynccallback委託來引用將在返回時調用的方法以及可以調用的回調返回方法endinvoke使用對IAyncResult接口的引用來檢索結果。檢查此鏈接:

http://www.codeproject.com/Articles/426120/Calling-a-method-in-Csharp-asynchronously-using-de

+0

爲了不使線程池線程等待,爲什麼不使用真正異步的'BeginAccept'? – 2014-10-01 18:08:03

+0

@Sriram Sakthivel,我的壞,我剛剛意識到我的解決方案不是最優的,BeginAccept肯定更好:) – 2014-10-01 18:09:59

0
 You can use AcceptAsync and register to the callback to do your processing after the accept is completed. Simple example below 

      void ManeLupe(Socket socket) 
      { 

       var args = new SocketAsyncEventArgs(); 
       args.Completed += Accept_Completed; 
       socket.AcceptAsync(args); 
      } 

      void Accept_Completed(object sender, SocketAsyncEventArgs e) 
      { 
       //do your processing here 
      }