即使我正在顺序处理,我也应该阻止

时间:2010-08-04 23:27:17

标签: c# .net windows-services

我有一个定期需要做一些工作的Windows服务。所以我设置了一个System.Timers.Timer来做到这一点。让我们假设处理时间可能大于计时器间隔。让我们假设如果发生这种情况将是一件非常糟糕的事情。

为了避免这种情况,我将Timer上的AutoReset设置为false,然后在我的进程中调用start。

public partial class Service : ServiceBase{

    System.Timers.Timer timer;


 public Service()
    {

    timer = new System.Timers.Timer();
    //When autoreset is True there are reentrancy problme 
    timer.AutoReset = false;


    timer.Elapsed += new System.Timers.ElapsedEventHandler(DoStuff);
}

 protected override void OnStart(string[] args)
 {

     timer.Interval = 1;
     timer.Start();

    }

 private void DoStuff(object sender, System.Timers.ElapsedEventArgs e)
 {

    Collection stuff = GetData();
    LastChecked = DateTime.Now;

    foreach (Object item in stuff)
    {
          item.Dosomthing(); //Do somthing should only be called once
     }     


    TimeSpan ts = DateTime.Now.Subtract(LastChecked);
    TimeSpan MaxWaitTime = TimeSpan.FromMinutes(5);


    if (MaxWaitTime.Subtract(ts).CompareTo(TimeSpan.Zero) > -1)
        timer.Interval = MaxWaitTime.Subtract(ts).TotalMilliseconds;
    else
        timer.Interval = 1;

    timer.Start();





 }

目前代码没有阻止,因为我知道它因为AutoReset = false而被顺序处理。但我可以做到这一点

lock(myLock)
{
    Collection stuff = GetData();
    LastChecked = DateTime.Now;

    foreach (Object item in stuff)
    {
          item.Dosomthing(); //Do somthing should only be called once
     }     

}

编辑:澄清我的问题

我已经将服务设计为单线程,因此我不需要锁定。如果我添加锁定,我仍然在我的性能预算范围内,因此性能不是没有理由的。

基本上我正在权衡双方,我正在努力理清Right Thing™是什么。 在“无锁”方面,我依赖于对我的代码正确性的设计。在“锁定”方面,我将添加不必要的代码。

哪个更好?

3 个答案:

答案 0 :(得分:2)

我要么全力保持线程安全,要么根本没有线程安全,只需在文档中写清楚该类是不是线程安全的。

最糟糕的事情是几年后回来,而不记得一切是否安全。然后你最终会浪费大量时间来调查你的代码,或者更糟糕的是,你最终会误导自己。

答案 1 :(得分:0)

如果多个线程将使用这些对象,则只需要lock。在您的情况下,您的设计可以防止这种情况发生,因此无需锁定。

在这种情况下,添加锁定的唯一真正好处是可以防止以后更改调度算法时出现问题。

答案 2 :(得分:0)

像其他人所说的那样,如果是单线程,则无需锁定。此外,您可以一起跳过计时器:

        TimeSpan maxInterval = new TimeSpan(0, 10, 0);
        while(true)
        {
            DateTime startTime = DateTime.UtcNow;


            //Do lots and lots of work


            TimeSpan ts = DateTime.UtcNow - startTime;
            ts = (ts > maxInterval ? new TimeSpan(0) : maxInterval-ts);
            Thread.Sleep(ts);
        }