Гарри, я тоже сталкивался с этим, также используя CCR. Мой опыт заключался в том, что, полностью отделив мои потоки диспетчера от блокировки на любом вводе / выводе, я мог потреблять и обрабатывать рабочие элементы гораздо быстрее, чем пул SqlConnection. Как только был достигнут максимальный лимит пула, я столкнулся с типом ошибок, которые вы видите.
Самое простое решение состоит в том, чтобы предварительно выделить несколько не объединенных в пул асинхронных объектов SqlConnection и разместить их на некотором центральном объекте Port . Затем всякий раз, когда вам нужно выполнить команду, сделайте это в итераторе примерно так:
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, а затем закройте полученное соединение и выбросьте его.