2013-04-26 208 views
1

我们有一些代码使用System.Timers.Timer来ping数据库连接,并检查是否存在一些已挂载的文件。设置定时器的代码是:System.Timers.Timer,比间隔运行更频繁,使用多线程

m_Timer = new System.Timers.Timer(TimeSpan.FromSeconds(10).TotalMilliseconds); 

m_Timer.Elapsed += (object xiSender, ElapsedEventArgs xiEventArgs) => 
{ 
    PingRemoteFolder(); 
    PingDatabase(); 
}; 

这发生在单例类的构造函数中。

我知道System.Timers.Timer将使用线程池中的多个线程,如果它每次尝试运行的操作都比所提供的时间间隔长,但在我们的情况中并非如此。

计时器的事件似乎比每10秒更频繁地发生,并且一次最多使用4或5个线程。

任何想法?此外,我们认为这可能与另一种情况有关,即我们在使用工作线程检查使用此计时器设置其值的类的属性的WPF应用程序的主线程上发生堆栈损坏时出现堆栈损坏。

.NET版本4.0 在Windows 2008R2

编辑:

而且当我们得到了WPF应用程序的主线程堆栈腐败,一个InvalidOperationException中的方法之一计时器事件抛出处理程序调用的消息“Timeout expired。在从池中获取连接之前已经超过了超时时间,可能是因为所有连接池都在使用中并且已达到最大池大小。

PingRemoteFolder()只是试图做Directory.GetFiles( “somepath”)

PingDatabase():

private void PingDatabase() 
{ 
    if(!string.IsNullOrEmpty(CurrentInstance.Name) && DoPing) 
    { 
     SqlConnection sqlConnection = null; 

     try 
     { 

      SqlConnectionStringBuilder sqlConnectionStringBuilder = new SqlConnectionStringBuilder(); 

      sqlConnectionStringBuilder.DataSource = CurrentInstance.Instance; 
      sqlConnectionStringBuilder.IntegratedSecurity = CurrentInstance.AuthenticationMode == SmoAuthenticationMode.WindowsAuthentication; 
      sqlConnectionStringBuilder.InitialCatalog = CurrentInstance.Name; 

      if(CurrentInstance.AuthenticationMode == SmoAuthenticationMode.SqlServerAuthentication) 
      { 
       sqlConnectionStringBuilder.UserID = CurrentInstance.UserName; 
       sqlConnectionStringBuilder.Password = CurrentInstance.Password; 
      } 

      sqlConnection = new SqlConnection(sqlConnectionStringBuilder.ToString()); 

      sqlConnection.Open(); 

      Assert.Condition(sqlConnection.State == ConnectionState.Open, "sqlConnection.State == ConnectionState.Open"); 

      IsCurrentInstanceReachable = true; 

     } 
     catch(Exception ex) 
     { 
      IsCurrentInstanceReachable = false; 
      CurrentInstance.Name = string.Empty; 
     } 
     finally 
     { 
      if(sqlConnection != null && (sqlConnection.State != ConnectionState.Closed && sqlConnection.State != ConnectionState.Broken)) 
      { 
       SqlConnection.ClearPool(sqlConnection); 

       sqlConnection.Close(); 
       sqlConnection = null; 
      } 
     } 
    } 
} 
+0

是平台/上下文WPF还是ASP.NET或...? – 2013-04-26 20:45:50

+0

您是如何得出4或5个线程正在使用的结论? – 2013-04-26 20:45:54

+0

@ChrisSinclair WPF – mclaassen 2013-04-26 20:48:00

回答

2

这听起来像有与数据库连接池的问题,和定时器调用PingDatabase()时的回调块。这会导致多个定时器回调线程同时存在。您可以通过调用m_Timer.Enabled = false在定时器函数的顶部并在函数结尾处调用m_Timer.Enabled = true来对此进行快速检查。这应该导致在任何给定时间只有一个线程存在。

m_Timer.Elapsed += (object xiSender, ElapsedEventArgs xiEventArgs) => 
{ 
    m_Timer.Enabled = false; 
    PingRemoteFolder(); 
    PingDatabase(); 
    m_Timer.Enabled = true; 
}; 
相关问题