Я понимаю пул соединений: если строка подключения точно такая же, мы повторно используем подключение, а не создаем новое.
Моя проблема в том, что я создаю много потоков для параллельной обработки. В этой «фиктивной» программе я создаю 500 потоков и позволяю функции ThreadPool обрабатывать их.
Шаги следующие:
Каждый поток составляет таблицу обновления на SQL. (Указывается отметка времени для обновления)
Затем поток находится в режиме ожидания от 1 до 10 секунд (произвольно).
В конце поток выполняет еще одно обновление в SQL (указав временную метку для времени окончания)
Затем выход из потока
class Program { static void Main(string[] args) { int numberOfThreads = 150; ThreadPool.SetMinThreads(numberOfThreads, numberOfThreads); ThreadPool.SetMaxThreads(numberOfThreads, numberOfThreads); List<Int64> chunkList = new List<Int64>(); int maxNumberOfChunks = 500; for (int i = 1; i < maxNumberOfChunks; i++) { chunkList.Add(i); } foreach (Int64 chunk_id in chunkList) { ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWorker), new arguments { chunk_id = chunk_id }); } Console.ReadLine(); } static void ThreadWorker(Object stateInfo) { arguments arguments = (arguments)stateInfo; Console.WriteLine("Chunk # : {0} is set to START", arguments.chunk_id); UpdateSQLdb(arguments.chunk_id, DateTime.Now, null, null, "START", null, null); Random random = new Random(); int mseconds = random.Next(1, 10) * 1000; System.Threading.Thread.Sleep(mseconds); Console.WriteLine("Chunk # : {0} is sleeping for {1} sec.", arguments.chunk_id, mseconds); Console.WriteLine("Chunk # : {0} ist set to END", arguments.chunk_id); UpdateSQLdb(arguments.chunk_id, null, DateTime.Now, null, "END", null, null); } struct arguments { public Int64 chunk_id; } static void UpdateSQLdb(Int64 CHUNK_ID, DateTime? START_TS = null, DateTime? END_TS = null, Enum CHUNK_STATUS = null, string error_messages = null, byte? NEW_CALCULATION_ATTEMPTS = null, byte? NEW_POSTPROCESS_ATTEMPTS = null) { using (SqlConnection conn = new SqlConnection("Data Source=C55S01;Initial Catalog=MCS_BATCH;Integrated Security=SSPI;Asynchronous Processing=True")) //Timeout=60;Max Pool Size=200;Pooling=True; { int result = -1; conn.Open(); //<-- Each time I open a connection. It creates a new instead of reusing one from the ConnectionPool try { using (SqlCommand cmd = new SqlCommand("TEST.UpdateSQL", conn)) { cmd.CommandTimeout = 300; cmd.CommandType = System.Data.CommandType.StoredProcedure; cmd.Parameters.Add("@CHUNK_ID", SqlDbType.BigInt, 15).Value = CHUNK_ID; cmd.Parameters.Add("@START_TS", SqlDbType.DateTime2, 7).Value = START_TS; cmd.Parameters.Add("@END_TS", SqlDbType.DateTime2, 7).Value = END_TS; cmd.Parameters.Add("@ERR_MESSAGE", SqlDbType.VarChar).Value = error_messages; cmd.Parameters.Add("@ReturnValue", System.Data.SqlDbType.Int, 4).Direction = System.Data.ParameterDirection.ReturnValue; try { result = cmd.ExecuteNonQuery(); int return_value = (int)cmd.Parameters["@ReturnValue"].Value; if (return_value != 0) { Console.WriteLine("1. Error in running TEST.UpdateSQL, return value is : {0}", cmd.Parameters["@ReturnValue"].Value); } } catch (SqlException ex) { UpdateSQLdb(CHUNK_ID, null, DateTime.Now, null, ex.Message.ToString(), null, null); Console.WriteLine("2. Error executing TEST.UpdateSQL : {0}", ex); } } } catch (Exception ex) { Console.WriteLine("3.Error in TEST.UpdateSQL : {0}", ex); throw; } if (conn.State == ConnectionState.Open) { Console.WriteLine("Closing connection...."); conn.Close(); } conn.Dispose(); } } }
}
Моя проблема в том, что я получаю System.InvalidOperationException was unhandled (Timeout expired. Время ожидания истекло до получения соединения из пула. Это могло произойти из-за того, что все соединения из пула использовались достигнут максимальный размер пула.)
Я отслеживал количество подключений на SQL-сервере, и он быстро достиг 100 подключений (что является максимальным количеством подключений по умолчанию в пуле).
Если вы пытались добавить эти параметры в строку подключения: Timeout = 60 "Max Pool Size = 200; Pooling = True;
Но это просто отложит проблему на более поздний этап, потому что пул соединений достигнет 200 и тайм-аут будет достигнут в какой-то момент.
Вопрос: почему подключения создаются снова и снова, вместо того, чтобы повторно использовать одно из пула подключений?
Любые подсказки, подсказки и советы приветствуются.