gpt4 book ai didi

c# - 将套接字和流代码从使用 BeginXXX 重写为 XXXAsync

转载 作者:太空宇宙 更新时间:2023-11-03 15:59:29 24 4
gpt4 key购买 nike

我正在尝试将一个应用程序从使用 BeginXXX 方法和 AsyncCallbacks 重写为使用 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 <= _maxTcpClients; i++) {
TcpClientState tt = new TcpClientState(new TcpClient(), i);
try {
tt.TcpClient.ConnectAsync(Host, Port).ContinueWith(t => 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;
}
}

在 TcpClient 的初始化速度(连接、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)

以及异步版本:

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<TcpClientState>();

for (int i = 1; i <= _maxTcpClients; i++)
{
TcpClientState tt = new TcpClientState(new TcpClient(), i);

Func<Task> 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();
}

关于c# - 将套接字和流代码从使用 BeginXXX 重写为 XXXAsync,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22027006/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com