使用BeginXXX重写套接字和流代码到XXXAsync

我正在尝试将使用AsyncCallbacks的BeginXXX方法重写为使用async / await和XXXAsync方法的应用程序。 但是我在性能方面遇到了一些麻烦。 例如,这里是原始代码的片段,用于初始化一堆连接:

... for (int i = 1; i <= _maxTcpClients; i++) { TcpClientState tt = new TcpClientState(new TcpClient(), i); try { tt.TcpClient.BeginConnect(Host, Port, ConnectCallback, tt); } catch (Exception ex) { Log.Debug( "Error on BeginConnect on RequestHandler (" + tt.HandlerId + ") request (" + tt.RequestId + ")", ex); CloseRequest(tt); } } ... private static void ConnectCallback(IAsyncResult ar) { TcpClientState tt = (TcpClientState)ar.AsyncState; Log.Debug("ConnectCallback on TcpClient (" + tt.TcpClientId + ")"); try { tt.TcpClient.EndConnect(ar); } catch (Exception ex) { Log.Debug("Error on EndConnect on TcpClient (" + tt.TcpClientId + ")", ex); CloseRequest(tt); Interlocked.Decrement(ref _maxTcpClients); return; } tt.SslStream = new SslStream(tt.TcpClient.GetStream(), false, Helper.ValidateServerCertificate, null); try { tt.SslStream.BeginAuthenticateAsClient(Host, SslAuthenticateCallback, tt); } catch (Exception ex) { Log.Debug("Error on BeginAuthenticateAsClient on TcpClient (" + tt.TcpClientId + ")", ex); CloseRequest(tt); Interlocked.Decrement(ref _maxTcpClients); } } 

我已经重写了以下内容:

 ... for (int i = 1; i  ConnectCallback(tt)); } catch (Exception ex) { Log.Debug("Error on ConnectAsync on TcpClient (" + tt.TcpClientId + ")", ex); CloseRequest(tt); Interlocked.Decrement(ref _maxTcpClients); return; } } ... private static void ConnectCallback(TcpClientState tt) { Log.Debug("ConnectCallback on TcpClient (" + tt.TcpClientId + ")"); tt.SslStream = new SslStream(tt.TcpClient.GetStream(), false, Helper.ValidateServerCertificate, null); try { tt.SslStream.AuthenticateAsClientAsync(Host).ContinueWith(t => SslAuthenticateCallback(tt)); } catch (Exception ex) { Log.Debug("Error on AuthenticateAsClientAsync on TcpClient (" + tt.TcpClientId + ")", ex); CloseRequest(tt); Interlocked.Decrement(ref _maxTcpClients); return; } } 

TcpClients的初始化速度(连接,ssl握手和其他)的速度似乎存在巨大的性能差异。 通过最初的方式,我可以在几秒钟内循环并初始化100个连接。 在重写之后,可以花费30秒的时间来完成同样的事情。 我可以在日志中看到各种回调函数是异步执行的,但所有内容都需要更长时间。 我不确定我做错了什么?

另外我知道在这种情况下,围绕Async方法的try catch不会做任何事情,但这不是现在的问题。

举一个速度差异的例子,这是一个调试日志片段,当原始代码循环10次时:

 2014-02-25 22:37:06,076 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (1) 2014-02-25 22:37:06,076 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (3) 2014-02-25 22:37:06,077 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (6) 2014-02-25 22:37:06,077 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (10) 2014-02-25 22:37:06,077 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (7) 2014-02-25 22:37:06,077 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (4) 2014-02-25 22:37:06,077 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (8) 2014-02-25 22:37:06,078 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (9) 2014-02-25 22:37:06,079 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (5) 2014-02-25 22:37:06,082 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (2) 

和Async版本:

 2014-02-25 22:37:51,569 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (1) 2014-02-25 22:37:51,583 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (2) 2014-02-25 22:37:51,936 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (5) 2014-02-25 22:37:51,969 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (3) 2014-02-25 22:37:52,133 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (4) 2014-02-25 22:37:52,311 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (6) 2014-02-25 22:37:52,382 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (8) 2014-02-25 22:37:52,452 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (9) 2014-02-25 22:37:52,466 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (7) 2014-02-25 22:37:52,856 [] DEBUG CPT.Client (null) - ConnectCallback on TcpClient (10) 

请尝试以下操作,看看它是否与您的BeginXXX / EndXXX版本基准进行比较。

 TcpClientState[] ConnectAll(string host, int port) { var states = new List(); for (int i = 1; i <= _maxTcpClients; i++) { TcpClientState tt = new TcpClientState(new TcpClient(), i); Func connectAsync = async () => { try { // note ConfigureAwait(false) await tt.TcpClient.ConnectAsync(host, port).ConfigureAwait(false); tt.SslStream = new SslStream(tt.TcpClient.GetStream(), false, Helper.ValidateServerCertificate, null); await tt.SslStream.AuthenticateAsClientAsync(host); // move here the code from SslAuthenticateCallback // and so on ... } catch (Exception ex) { // you really want to do --_maxTcpClients ? Interlocked.Decrement(ref _maxTcpClients); Debug.Print(ex.ToString()); throw; // re-throw or handle } }; tt.ConnectionTask = connectAsync(); states.Add(tt); } return states.ToArray(); }