在BeginReceive回调中异步/等待

时间:2015-02-26 17:50:31

标签: c# multithreading asynchronous async-await asyncsocket

据说,BeginReceiveBeginSend回调未在.Net ThreadPool上执行,而是在IOCP ThreadPool上执行。对于高性能服务器,IOCP线程尽快返回池是至关重要的,这意味着BeginReceiveBeginSend的回调中没有重大提升。如果我调用异步方法并在回调中等待它,该怎么办? 是否意味着IOCP线程将返回到线程池,当异步操作完成时,回调方法将继续在另一个可用的IOCP线程上?

2 个答案:

答案 0 :(得分:3)

AFAIK,无法保证这些回调将在IOCP线程上执行。

如果使回调异步并使用await,则回调线程将返回到线程池(无论是IOCP线程还是常规线程池线程)。稍后,当异步方法恢复时,它将在常规线程池线程上恢复,而不是IOCP线程(AFAIK这是未记录的但只是有意义)。

但是,我无法想象您实际上想要这样做的用例。如果您wrapped BeginReceive/EndReceive and BeginSend/EndSend within a task-based API并且始终使用async / await,则代码会更清晰。

答案 1 :(得分:2)

如果您拨打await async方法,则会使用ThreadPool主题执行续会(除非SynchronizationContextTaskScheduler另有指定,这不是这种情况。)

但是,除非async应该避免,否则您无法进行回调async void。所以我不明白你如何在这个回调中合理await

使用BeginX/EndXTask转换为FromAsync会更加简单,然后您可以通过更多控制来处理它上的延续。例如,您可以指定TaskScheduler.Defaul t以确保延续在ThreadPool线程上运行。

var task = Task.Factory.FromAsync(BeginX, EndX,...);
task.ContinueWith(ante => {...}, null, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default)