我有一个线程(通过new Thread(new ThreadStart(...))
调用),当我的软件在数据库中进行轮询时,它总是在运行。
以一种非常简单的方式,它基本上完成以下操作:
void Polling()
{
Thread.Sleep(500);
methodA();
if (certainTimePassed)
methodB();
if (anotherCertainTimePassed)
methodC();
...
}
void methodA()
{
SIDataContext db = new SIDataContext(_host.Config.ConnectionString);
if (looksForSomeData())
raiseSomeEvents();
db.Connection.Close();
}
它按小时运行,一小时又一小时都很好。然而,如果我通过使looksForSomeData()始终返回true(即不断插入它搜索的数据)并同时使用另一个在数据库中查询大型SELECT的软件部分来强调应用程序,它最终会产生以下结果(始终在MethodA中,可能是因为它是调用最多的一个):
超时已过期。在获取来自池的连接。发生这种情况的原因可能是连接正在使用,已达到最大池大小。
我认为这可能是一个更复杂的问题。但由于我只有几个月的LINQ DataContext()经验,我不确定。
需要注意的事项/我尝试过:
- 使用
using
而不是db.Connection.Close()
- 它不可能打开连接、引发异常和不关闭连接,因为如果在该线程中引发异常,软件将退出
raiseSomeEvents()
中引发的事件不会累积(可能),因为有某种信号量解决方案可以使引发的事件仅在尚未运行时发生- 发现异常,什么也不做。软件速度减慢,甚至冻结了一段时间,然后恢复正常(似乎连接最终被释放)
我很感激任何能帮助我诊断问题所在的东西。
这可能只是连接池。启动一个新的连接是非常昂贵的,所以.Net会保持连接的打开状态并重复使用它们。
您的表上有索引吗?大量插入还会导致索引更新,这可能会对select语句产生不利影响。此外,select语句也可能使用临时数据库来确保它们是可重复的,这同样可能是昂贵的。这些可能会产生累积影响,从而增加完成快速操作所需的时间。
在我看来,您的查询运行时间异常长(即超过10-15秒)。在这些情况下,连接可能会超时。我建议您尝试使用应用程序可能传递的任何参数自行运行查询,如果查询需要很长时间,请查看是否有任何方法可以改进SQL。
您可以随时参考:超时已过期。在操作完成或服务器没有响应之前经过的超时时间。语句已终止
看看您的methodA()
,告诉我如果在创建数据上下文后但在关闭它之前抛出异常或中止线程,您认为会发生什么?正确的答案是,连接将保持打开状态,至少一段时间。
必须将与数据库访问有关的任何内容封装在try
/finally
块中,以便连接作为finally
的一部分关闭。最简单的方法是使用using
块。我知道你说过你试过了,但你应该发布代码:
void methodA()
{
using (SIDataContext db = new SIDataContext(_host.Config.ConnectionString))
{
if (looksForSomeData())
raiseSomeEvents();
}
}