3

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

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

在谷歌上搜索这个问题的解决方案时,我偶然发现了一些建议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 有什么意义呢?所有 IOCP 的优点都被RegisterWaitForSingleObject.

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

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

4

1 回答 1

2

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

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

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

不,它确实降低了它的有效性,但是由于 有一个线程池RegisterWaitForSingleObject,它不会杀死它的有用性。

请注意,在 C# 5 中,我通常会使用async/await支持超时来处理这个问题。 Task.Delay可以用来简单地处理这个问题,或者您可以使用 Timer 制作扩展方法来处理任何Task.

于 2013-08-15T20:15:54.727 回答