Jim*_*ica 1 c# asynchronous threadpool async-await
我正在研究一种非常流行的c#代理服务器.在其中有代码如(我故意隐藏代理服务器身份,因为我觉得很难讲故事,如果确实是错误的话).
private void OnConnectionAccepted(TcpClient cl)
{
....
Task.Run(async () =>
{
await HandleClientRequest();
});
Task.Run(async () =>
{
TcpClient cl = await listener.AcceptTcpClientAsync();
OnConnectionAccepted(cl);
});
}
Run Code Online (Sandbox Code Playgroud)
HandleClientRequest
某些异步网络调用在哪里,例如从客户端读取请求并将其重复发送到服务器,就像您希望代理一样.
listener.AcceptTcpClientAsync
只是等待来自浏览器的下一个连接.
所以看起来Task.Run的重点只是允许AcceptTcpClientAsync
在HandleClientRequest
忙碌时被调用.
这似乎违背了我一直在阅读的建议,例如.http://blog.stephencleary.com/2013/10/taskrun-etiquette-and-proper-usage.html因为Task.Run正在包装网络,而不是CPU调用.
那么它应该如何工作呢,如果这是错的,它应该使用ThreadPool.QueueUserWorkerItem吗?
顺便说一句,上下文通常是一个控制台应用程序.
这似乎违背了我一直在阅读的建议...因为Task.Run包装网络,而不是CPU调用.
通常,Task.Run
不应该用于I/O. 但是,该建议适用于应用程序代码,甚至有几个例外.
在这种情况下(检查代理服务器的核心接受/处理逻辑),我们正在查看的代码更多的是框架,其中"应用程序"在内部HandleClientRequest
.(请注意,此代码托管在Console或Win32服务中,而不是在ASP.NET中).
为了绘制并行,ASP.NET将侦听连接,并从线程池中获取一个线程来处理请求.这对于框架来说是完全自然的.
以下是使用的一些原因Task.Run
,对于此特定情况可能有效,也可能无效:
HandleClientRequest
使用这些API,将它包装在一个中是有意义的Task.Run
.SynchronizationContext
.但是,这似乎并非如此.HandleClientRequest
在它开始实际工作之前有一些"管家",那么将它包装成一个Task.Run
听众没有被阻挡可能是有益的.Task.Run
不存在并且同时进行了大量连接,那么堆栈可能会溢出.我认为这是第二个目的,Task.Run
因为我不能想到它会有任何其他目的.那么它应该如何工作呢,如果这是错的,它应该使用ThreadPool.QueueUserWorkerItem吗?
绝对不!Task.Run
是使用线程池的适当方法.(除非你有一个非常聪明的团队,你可以显示出可测量的性能差异).
因此,似乎Task.Run的目的只是允许在HandleClientRequest繁忙时调用AcceptTcpClientAsync.
的使用Task.Run
仍然是问题的最好,因为任务应早晚期待.当前标准的,从任何异常HandleClientRequest
,AcceptTcpClientAsync
以及OnConnectionAccepted
将会被丢弃.如果HandleClientRequest
和OnConnectionAccepted
两个有顶级try
块,那将是美好的,但任何的异常AcceptTcpClientAsync
会导致整个代理服务器停止工作.并且该方法可以抛出异常,尽管很少见.
归档时间: |
|
查看次数: |
478 次 |
最近记录: |