Async/await 在 BeginReceive 回调中
Async/await within BeginReceive Callback
据说 BeginReceive
和 BeginSend
回调不会在 .Net ThreadPool
上执行,而是在 IOCP ThreadPool
上执行。对于高性能服务器,IOCP 线程尽快 return 到池中至关重要,这意味着 BeginReceive
和 BeginSend
的回调中没有繁重的工作。如果我调用异步方法并在回调中等待它会怎样?
这是否意味着 IOCP
线程将 return 到线程池,当异步操作完成时回调方法将在另一个可用的 IOCP
线程上继续?
据我所知,不能保证这些回调会在 IOCP 线程上执行。
如果您使回调异步并使用 await
,则回调线程将返回到线程池(无论是 IOCP 线程还是常规线程池线程)。稍后,当异步方法恢复时,它将在常规线程池线程上恢复,而不是 IOCP 线程(据我所知,这没有记录但很有意义)。
但是,我无法想象您实际想要执行此操作的用例。如果您 wrapped BeginReceive
/EndReceive
and BeginSend
/EndSend
within a task-based API 并且在整个过程中只使用 async
/await
,代码会更清晰。
如果您调用 await
一个 async
方法,将使用 ThreadPool
线程执行延续(除非 SynchronizationContext
或 TaskScheduler
,这里不是这种情况)。
但是,您不能进行回调 async
,除非它是 async void
,应该避免。所以我看不出你如何合理地await
这个回调中的任何东西。
将 BeginX/EndX
转换为带有 FromAsync
的 Task
会简单得多,然后您可以通过更多控制来处理它的延续。例如,您可以指定 TaskScheduler.Defaul
t 以确保延续在 ThreadPool
线程上运行。
var task = Task.Factory.FromAsync(BeginX, EndX,...);
task.ContinueWith(ante => {...}, null, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default)
据说 BeginReceive
和 BeginSend
回调不会在 .Net ThreadPool
上执行,而是在 IOCP ThreadPool
上执行。对于高性能服务器,IOCP 线程尽快 return 到池中至关重要,这意味着 BeginReceive
和 BeginSend
的回调中没有繁重的工作。如果我调用异步方法并在回调中等待它会怎样?
这是否意味着 IOCP
线程将 return 到线程池,当异步操作完成时回调方法将在另一个可用的 IOCP
线程上继续?
据我所知,不能保证这些回调会在 IOCP 线程上执行。
如果您使回调异步并使用 await
,则回调线程将返回到线程池(无论是 IOCP 线程还是常规线程池线程)。稍后,当异步方法恢复时,它将在常规线程池线程上恢复,而不是 IOCP 线程(据我所知,这没有记录但很有意义)。
但是,我无法想象您实际想要执行此操作的用例。如果您 wrapped BeginReceive
/EndReceive
and BeginSend
/EndSend
within a task-based API 并且在整个过程中只使用 async
/await
,代码会更清晰。
如果您调用 await
一个 async
方法,将使用 ThreadPool
线程执行延续(除非 SynchronizationContext
或 TaskScheduler
,这里不是这种情况)。
但是,您不能进行回调 async
,除非它是 async void
,应该避免。所以我看不出你如何合理地await
这个回调中的任何东西。
将 BeginX/EndX
转换为带有 FromAsync
的 Task
会简单得多,然后您可以通过更多控制来处理它的延续。例如,您可以指定 TaskScheduler.Defaul
t 以确保延续在 ThreadPool
线程上运行。
var task = Task.Factory.FromAsync(BeginX, EndX,...);
task.ContinueWith(ante => {...}, null, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default)