哈利,我也遇到过这个问题,也是在使用 CCR 时。我的经验是,将调度程序线程与任何 I/O 上的阻塞完全解耦后,我可以比 SqlConnection 池处理的更快地消耗和处理工作项。一旦达到最大池限制,我就会遇到您所看到的那种错误。
最简单的解决方案是预先分配一些非池化的异步 SqlConnection 对象并将它们发布到某个中心 Port<SqlConnection> 对象。然后,每当您需要执行命令时,请在迭代器中执行以下操作:
public IEnumerator<ITask> Execute(SqlCommand someCmd)
{
// Assume that 'connPort' has been posted with some open
// connection objects.
try
{
// Wait for a connection to become available and assign
// it to the command.
yield return connPort.Receive(item => someCmd.Connection = item);
// Wait for the async command to complete.
var iarPort = new Port<IAsyncResult>();
var iar = someCmd.BeginExecuteNonQuery(iarPort.Post, null);
yield return iarPort.Receive();
// Process the response.
var rc = someCmd.EndExecuteNonQuery(iar);
// ...
}
finally
{
// Put the connection back in the 'connPort' pool
// when we're done.
if (someCmd.Connection != null)
connPort.Post(someCmd.Connection);
}
}
使用 Ccr 的好处在于,将以下功能添加到这段基本代码中是微不足道的。
- 超时 - 只需进行初始接收(对于可用连接),一个带有超时端口的“选择”。
- 动态调整池大小。要增加池的大小,只需将新的打开的 SqlConnection 发布到“connPort”。要减小池的大小,请在 connPort 上产生一个接收,然后关闭接收到的连接并将其丢弃。