【发布时间】:2024-04-14 15:45:02
【问题描述】:
我已经确定了我的 TCP 应用程序中的一个瓶颈,我为了这个问题而对其进行了简化。
我有一个MyClient 类,它代表客户端何时连接;我还有一个MyWrapper 类,它代表满足某些条件的客户端。如果MyClient满足某些条件,则它有资格成为包装器。
我想公开一个允许调用者等待MyWrapper的方法,该方法应该处理无效MyClients的协商和拒绝:
public static async Task StartAccepting(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
var wrapper = await AcceptWrapperAsync(token);
HandleWrapperAsync(wrapper);
}
}
因此AcceptWrapperAsync 等待一个有效的包装器,而HandleWrapperAsync 异步处理包装器而不阻塞线程,因此AcceptWrapperAsync 可以尽快恢复工作。
该方法在内部的工作原理是这样的:
public static async Task<MyWrapper> AcceptWrapperAsync(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
var client = await AcceptClientAsync();
if (IsClientWrappable(client))
return new MyWrapper(client);
}
return null;
}
public static async Task<MyClient> AcceptClientAsync()
{
await Task.Delay(1000);
return new MyClient();
}
private static Boolean IsClientWrappable(MyClient client)
{
Thread.Sleep(500);
return true;
}
这段代码模拟每秒有一个客户端连接,并且需要半秒来检查连接是否适合包装器。 AcceptWrapperAsync 循环直到生成有效的包装器,然后返回。
这种运作良好的方法存在缺陷。在IsClientWrappable 执行期间,不能接受更多的客户端,当大量客户端同时尝试连接时会造成瓶颈。恐怕在现实生活中,如果服务器在连接了很多客户端的情况下出现故障,那么上升不会很好,因为所有客户端都会同时尝试连接。我知道同时连接所有这些非常困难,但我想加快连接过程。
使IsClientWrappable异步,只会确保执行线程在协商完成之前不会被阻塞,但无论如何都会阻塞执行流程。
如何改进这种方法以不断接受新客户,但仍然能够等待使用 AcceptWrapperAsync 的包装器?
【问题讨论】:
-
这似乎是 Reactive Extensions (Rx) 的一个很好的用例
-
Rx 对于这将是一个矫枉过正。看来Dataflow更有意义。
-
使用 RX,您将数据推送到订阅者,而使用 DataFlow,您将数据推送到消费者。 :)
-
好吧,看来RX远不止这些。数据流只是异步工作的类的集合:P
标签: c# multithreading asynchronous async-await asyncsocket