我有3个相同的程序(使用topshelf制作),作为3个不同部门的3个独立服务运行。当它们运行时,它们使用定时器继续访问数据库 - 主要是为了继续发送Alive信号或清除旧日志。最近我被要求只为其中一个部门添加额外的计时器
Random r = new Random(); //to avoid possible deadlock we save the timestamp on random time
int hourly = 1000 * 60 * 60; //this is an hour
Timer TimerItem = new Timer(TimerCallBack, null, 0, r.Next(20000, 25000)); //alive timer
Timer purgeLogs = new Timer(TimerPurgeLogs, null,0,hourly); //purge logs timer
if (selDep == "planners")
{
Timer UpdatePlannes = new Timer(TimerUpdatePlanners, null, 0, r.Next(50000,60000)); //planners update
}
private static void TimerUpdatePlanners (Object o)
{
string conn = System.Configuration.ConfigurationManager.ConnectionStrings["Microsoft.Rtc.Collaboration.Sample.Properties.Settings.lynccallrosterConnectionString"].ToString();
if (selDep == "planners") //Only for planners - auto turn the forwading on for everyone except the current person
{
string updateCommand = "update employees set on_call = 1 where Department ='Planners' and gkey <> (Select gkey from currently_on_call where Department ='Planners')";
using (SqlConnection updatePlanners = new SqlConnection(conn))
{
SqlCommand executeUpdate = new SqlCommand(updateCommand, updatePlanners);
try
{
updatePlanners.Open();
executeUpdate.ExecuteNonQuery();
updatePlanners.Close();
}
catch { }
}
}
不幸的是,在我完成此操作之后,它导致了其他尝试读取同一数据库的程序出现问题,因为它以某种方式使数据库死锁(SQL 2005)。
我无法在这里看到死锁的原因:定时器每50-60秒执行一次,命令执行持续几毫秒,但似乎连接始终保持打开状态 - 在活动监视器中我可以看到十几个更新命令,这些命令会阻塞数据流量。
有趣的是,这个问题只发生在程序作为服务运行时 - topsehlf允许将服务作为控制台应用程序运行,当它在此模式下运行时,我看不到任何死锁或不必要的更新命令在队列中等待。
我做错了什么?
编辑:我已按照建议尝试在try-catch中添加Dispose()
方法
try
{
updatePlanners.Open();
executeUpdate.ExecuteNonQuery();
updatePlanners.Close();
}
catch { }
finally
{
executeUpdate.Dispose();
updatePlanners.Dispose();
}
但这仍然无法解决死锁问题。
EDIT2:我想通过在计时器启动时添加延迟,使用try-and-error方法解决了它:
Timer UpdatePlanners = new Timer(TimerUpdatePlanners, null, r.Next(10000, 20000), r.Next(10000, 20000));
为什么有这么多的UPDATE产生仍然让我感到困惑,但至少现在它们并没有相互死锁,因为每一个都会在服务启动/计时器滴答的不同时间产生。