该问题可以通过 MSDN 的以下引用来描述:
在异步方法调用(例如 BeginExecuteReader)期间,CommandTimeout 属性将被忽略。
在谷歌上搜索这个问题的解决方案时,我偶然发现了一些建议Task.Factory.FromAsync
与ThreadPool.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)锁定?