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



这个问题可以通过MSDN中的以下引用来描述:

在异步方法期间将忽略CommandTimeout属性调用,如BeginExecuteReader。

在谷歌上搜索这个问题的解决方案时,我偶然发现了许多建议将Task.Factory.FromAsyncThreadPool.RegisterWaitForSingleObject结合使用的帖子。

关于SO,人们可以在这里和这里查看,尽管这两个讨论的是异步web请求,而不是SQL命令。但问题是一样的——从异步SQL命令/Web请求中超时。

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

我不明白这里有什么。异步IO方法利用IO完成端口回调来返回结果。当这样的IO操作开始时,调用线程会返回到线程池中,供其他请求重用。

另一方面,根据MSDN:

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

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

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

但是,在这种情况下使用异步IO有什么意义呢?CCD_ 5杀死了IOCP的所有优点。

另一方面,根据MSDN的博客,RegisterWaitForSingleObject优化了等待,将同一线程的多个句柄批处理成一个对WaitForMultipleObjects的调用,这反过来又受到它可以等待的句柄数量的限制,即64个。

那么,如果每个请求从同一线程发出65个异步IO请求并结合RegisterWaitForSingleObject,那么有多少线程池线程(b)被锁定?

那么,如果每个请求都有65个异步IO请求与RegisterWaitForSingleObject一起从同一线程发出,那么有多少线程池线程被锁定?

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

后者不是扼杀了前者的效用吗?

没有。它确实降低了它的有效性,但由于RegisterWaitForSingleObject中有线程池,所以它并没有破坏它的有用性。

请注意,在C#5中,我通常会使用带有超时的async/await支持来处理此问题。Task.Delay可以简单地用于处理此问题,也可以使用Timer制作一个扩展方法来处理任何Task上的超时。

相关内容

  • 没有找到相关文章

最新更新