0

仅以 .net 套接字为例,我使用:

TcpListener listener = new TcpListener(ip, port);
while(true)
{
    TcpClient client = socket.AcceptTcpClient();
    DoSomethingWithClient(client);
}

但另一种方式似乎类似于(基于http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.beginaccepttcpclient.aspx):

public static ManualResetEvent tcpClientConnected = new ManualResetEvent(false);

public static void DoBeginAcceptTcpClient(TcpListener listener)
{
    tcpClientConnected.Reset();
    listener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpClientCallback), listener);
    tcpClientConnected.WaitOne();
}

public static void DoAcceptTcpClientCallback(IAsyncResult ar) 
{
    TcpListener listener = (TcpListener) ar.AsyncState;
    TcpClient client = listener.EndAcceptTcpClient(ar);
    DoSomethingWithClient(client);
    tcpClientConnected.Set();
}

恕我直言,异步风格需要 3 倍的代码,看起来像 goto spaghetti - 它难以阅读,并迫使您分离出相关代码。那么为什么要使用异步方式呢?想必它一定有什么优势吧?

4

3 回答 3

5

它的优点是不会阻塞调用者的线程,这在您创建即使在执行工作时也应该保持响应的交互式应用程序时尤其重要。

由于 C# 5 有async/await使这种代码容易编写和阅读。

于 2013-07-01T14:22:43.727 回答
1

正如其他人所提到的,异步代码使您能够使用更少的线程,从而更好地扩展(对于服务器)并保持响应(对于 UI 客户端)。

特别是关于 TCP/IP 套接字,使用异步方法还有另一个原因:您可以同时写入和读取。这在一般情况下是必要的,以防止死锁;所有大型通用服务器都专门使用异步套接字。

VS2012 中的新async/await使编写异步代码的方式更加自然。但是,由于读写流是独立的,实际的异步socket编程还是比较复杂的。我在我的博客上有一个介绍,async最后有一些很好的后续资源。

我相信您只是将套接字用作同步或异步事物的示例,但如果您真的对在此级别使用套接字感兴趣,您可能还会发现我的TCP/IP .NET 套接字常见问题解答很有帮助。

于 2013-07-01T15:06:37.703 回答
0

对于大量并发客户端,使用异步与同步方法允许应用在执行相同工作时使用更少的线程。

例如,我刚刚运行了一个应用程序,该应用程序首先使用大约 30 个线程创建/管理 2000 个传出连接(随着线程返回线程池而减少)。

然而,以这种方式编程通常会有点棘手,并且可能有点滑坡,因为您必须减少所有阻塞线程的来源以最大限度地发挥优势。

新的async/await语法减少了代码意大利面条的问题,并允许您编写包含异步调用的常规“不间断”方法。

如果您不能使用 C# 5 和async/await语法,还有其他方法,例如 J. Richter 的 AsyncEnumerator。

于 2013-07-01T14:44:44.453 回答