在我的多线程窗口服务中,我在每个线程上打开到db的连接,之后我处理这些连接,尽管问题是当我在系统上执行查询时,一些在db上没有关闭。sysprocesses表。
我运行了两个单元测试,看到了一些奇怪的行为,在第一个单元测试中,我运行了一个有100个任务的循环,在每个任务中我都打开了一个新连接。在这些完成后(我通过WaitAll()看到),我看到一些连接仍然挂在数据库中。在第二个单元测试中,当我在没有并行执行的情况下运行几个open/dispose时,它可以很好地处理它们,并且在我的db中没有挂起连接。
问题是,在我的Windows服务中,这些挂起的连接正在被添加,最终没有更多的地方用于新的连接,数据库对用户来说是不可用的。
下面是代码,第一个是并行的,第二个是不并行的:
[TestMethod]
public void TestMultiThreadedAccessToExplicitObjectContext()
{
int taskSize = 100;
List<Task> taskList = new List<Task>();
int goodSources = 0;
for (int i = 0; i < taskSize; i++)
{
Task newTask = Task.Factory.StartNew(() =>
{
System.Data.Objects.ObjectContext objectContext = new PersoniteEntities();
objectContext.Connection.Open();
objectContext.Dispose();
Thread.Sleep(1200);
});
taskList.Add(newTask);
}
Task.WaitAll(taskList.ToArray());
GC.Collect();
total += goodSources;
}
[TestMethod]
public void TestMultiThreadedAccessToExplicitObjectContextInline()
{
System.Data.Objects.ObjectContext objectContext1 = new PersoniteEntities();
objectContext1.Connection.Open();
objectContext1.Dispose();
System.Data.Objects.ObjectContext objectContext2 = new PersoniteEntities();
objectContext2.Connection.Open();
objectContext2.Dispose();
System.Data.Objects.ObjectContext objectContext3 = new PersoniteEntities();
objectContext3.Connection.Open();
objectContext3.Dispose();
System.Data.Objects.ObjectContext objectContext4 = new PersoniteEntities();
objectContext4.Connection.Open();
objectContext4.Dispose();
System.Data.Objects.ObjectContext objectContext5 = new PersoniteEntities();
objectContext5.Connection.Open();
objectContext5.Dispose();
}
谢谢
使用连接池,每个工作进程(或本例中的线程)都有自己的连接池。因此,如果您将最大池大小设置为3,并生成100个线程,则可能有300个连接。
来自有类似问题的人的更多信息:
ODP。. NET连接池参数
和MS关于连接池如何工作的一些文档,以及连接池碎片的解释:
MSDN - SQL Server连接池(ADO.NET)
解决方案1
在连接字符串
中关闭连接池MSDN -连接字符串-池
例如:当此键的值被设置为true时,任何新创建的当应用程序关闭连接时,连接将被添加到池中。在下次尝试打开同一连接时,该连接将是从水池里捞出来的。如果连接有,则认为它们是相同的相同的连接字符串。不同的连接有不同的连接字符串。
该键的取值为true、false、yes或no。
<add
name="AppEntities"
connectionString="
metadata=res://*/App_Code.AppModel.csdl|res://*/App_Code.AppModel.ssdl|res://*/App_Code.AppModel.msl;
provider=System.Data.SqlClient;
provider connection string="
Data Source=.;
Initial Catalog=Example;
Integrated Security=True;
Pooling=False;
MultipleActiveResultSets=True
""
providerName="System.Data.EntityClient"
/>
解决方案2
看起来可能有一个涉及信号量的解决方案,详细说明如下:
使用多线程服务的数据库连接池
假设这是您在测试中运行的所有代码,您可能不会查看挂起的连接。这是连接池的正常行为。
当你使用一个线程。net可以重用相同的物理连接,因为它已经从上一个命令关闭。对于多线程,它必须打开几个物理连接来处理并行请求。
p。您应该使用using语句而不是手动. dispose,因为如果open之后的内容抛出异常,则可能会使连接打开的时间比预期的长。因此,您可能会耗尽连接。