Task.Factory.FromAsync和RegisterWaitForSingleObject - 后者不会杀死前者的用处吗?

时间:2013-08-15 20:06:50

标签: .net multithreading asynchronous io timeout

问题可以通过以下MSDN引用来描述:

  

在异步方法期间将忽略CommandTimeout属性   诸如BeginExecuteReader之类的调用。

在Google上搜索此问题的解决方案我偶然发现了一些建议将Task.Factory.FromAsyncThreadPool.RegisterWaitForSingleObject结合使用的帖子。

On SO可以查看herehere,尽管这两个讨论异步Web请求,而不是SQL命令。但问题完全相同 - 从异步SQL命令/ Web请求中超时。

建议的方法是调用Task.Factory.FromAsync然后ThreadPool.RegisterWaitForSingleObject在与任务相对应的句柄上等待或超时。

我在这里听不懂。异步IO方法正在使用IO完成端口回调以返回结果。当这样的IO操作开始时,调用线程返回到线程池以供其他请求重用。

另一方面,根据MSDN:

  

RegisterWaitForSingleObject方法将指定的委托排队到线程池

  

等待线程使用Win32 WaitForMultipleObjects函数   监控已注册的等待操作。

这意味着它会阻止线程池线程,直到我们的异步IO返回或发生超时。如果我的理解是正确的,那么正在使用N个异步IO将阻止并锁定N个线程池线程,如果我们使用这种技术。

但是,在这种情况下使用异步IO有什么意义呢?所有IOCP善意都被RegisterWaitForSingleObject杀死。

另一方面,根据this MSDN blogRegisterWaitForSingleObject优化等待,将同一个线程中的多个句柄批处理到一个WaitForMultipleObjects的调用,而RegisterWaitForSingleObject依次限制它可以等待的手柄数量 - 即64.

那么,如果每个请求的同一个线程和{{1}}有65个异步IO请求,那么(b)锁定了多少个线程池线程?

1 个答案:

答案 0 :(得分:2)

  

那么,如果每个请求的同一个线程与RegisterWaitForSingleObject一起发出65个异步IO请求,那么(b)锁定了多少个线程池线程?

两个(对于RegisterWaitForSingleObject调用) - 每个ThreadPool线程可以处理64个请求(从技术上讲,它是MAXIMUM_WAIT_OBJECTS的值,实际上是64)。

  

后者不会杀死前者的用处吗?

没有。它确实降低了它的有效性,但由于RegisterWaitForSingleObject中存在一组线程,因此它不会破坏它的实用性。

请注意,在C#5中,我通常会使用async / await支持超时来处理此问题。 Task.Delay可以用来简单地处理这个问题,或者你可以extension method using a Timer来处理任何Task的超时。