【问题标题】:Should I block even when I'm sequentially processing即使按顺序处理,我也应该阻止吗
【发布时间】:2011-05-10 01:51:25
【问题描述】:

我有一个定期需要做一些工作的 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™ 是什么。 在“无锁”方面,我依靠一个装置来保证我的代码的正确性。在“锁定”方面,我将添加不必要的代码。

哪个更好?

【问题讨论】:

    标签: c# .net windows-services


    【解决方案1】:

    我要么全力以赴线程安全,要么根本不做线程安全,只是在你的文档中非常清楚地写下这个类不是线程安全的。

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        就像其他人所说的,如果它是单线程,则不需要锁。此外,您可以一起跳过计时器:

                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);
                }
        

        【讨论】:

        • 如果我执行 Thread.Sleep,服务将在停止或暂停时无响应(挂起),直到 Thread.Sleep 结束。
        • 对于单线程应用程序为真;在处理 OnStop (和其他)事件之前,您必须等待 Thread.Sleep 完成。但是,如果您将 DoStuff 放在自己的线程中,那么应该没问题。
        猜你喜欢
        • 2011-03-23
        • 1970-01-01
        • 2011-01-02
        • 2019-10-13
        • 2016-09-05
        • 1970-01-01
        • 1970-01-01
        • 2015-09-22
        • 1970-01-01
        相关资源
        最近更新 更多