Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 正在同步计时器。停止时计时器已用方法_C#_.net_Synchronization_Timer - Fatal编程技术网

C# 正在同步计时器。停止时计时器已用方法

C# 正在同步计时器。停止时计时器已用方法,c#,.net,synchronization,timer,C#,.net,Synchronization,Timer,关于System.Timers.Timer的以下引用: Timer.Appeased事件在上引发 线程池线程,因此 事件处理方法可能在一个服务器上运行 线程同时调用 Timer.Stop方法在另一个服务器上运行 线这可能会导致 事件发生后引发的已用事件 调用Stop方法。这场比赛 这种情况不能简单地预防 通过比较SignalTime属性 使用停止方法时的时间 调用,因为事件处理 方法可能已在执行时 停止方法被调用,或者可能被调用 开始执行之间的时刻 当调用Stop方法时 保存停止时间的时刻。如果

关于System.Timers.Timer的以下引用:

Timer.Appeased事件在上引发 线程池线程,因此 事件处理方法可能在一个服务器上运行 线程同时调用 Timer.Stop方法在另一个服务器上运行 线这可能会导致 事件发生后引发的已用事件 调用Stop方法。这场比赛 这种情况不能简单地预防 通过比较SignalTime属性 使用停止方法时的时间 调用,因为事件处理 方法可能已在执行时 停止方法被调用,或者可能被调用 开始执行之间的时刻 当调用Stop方法时 保存停止时间的时刻。如果 防止螺纹断裂是至关重要的 它从调用Stop方法 在事件处理过程中继续 方法仍在执行,请使用 鲁棒同步机制,如 作为班长或 比较交换方法。使用 CompareExchange方法可以是 在 计时器。停止方法

有人能举一个健壮的同步机制(比如Monitor类)的例子来解释这到底意味着什么吗


我认为这意味着以某种方式使用锁,但我不确定您将如何实现它。

这就是它的建议

是C编译器用于lock语句的类

也就是说,如果上述问题在你的情况下是个问题,那么它只是个问题。整个语句基本上可以转换为在调用Stop之后立即发生计时器事件。如果这是一个问题,你需要处理它。取决于你的定时器在做什么,它可能是一个问题,也可能不是

如果这是一个问题,页面会显示一个健壮的方法来处理这个问题。只需从示例中复制代码,并根据需要进行修改。

尝试:

lock(timer) {
timer.Stop();
}

这里有一个非常简单的方法来防止这种竞争情况的发生:

private object _lock = new object();
private Timer _timer; // init somewhere else

public void StopTheTimer()
{
    lock (_lock) 
    {
        _timer.Stop();
    }
}

void elapsed(...)
{
    lock (_lock)
    {
        if (_timer.Enabled) // prevent event after Stop() is called
        {
            // do whatever you do in the timer event
        }
    }
}

可靠地停止System.Timers.Timer确实是一项重大工作。最严重的问题是,由于threadpool调度程序算法,它用来调用已用事件的线程池线程可以备份。有几个备份电话并不罕见,有数百个备份电话在技术上是可能的

您将需要两个同步,一个用于确保仅在没有运行已用事件处理程序时停止计时器,另一个用于确保这些备份的TP线程不会造成任何损害。像这样:

    System.Timers.Timer timer = new System.Timers.Timer();
    object locker = new object();
    ManualResetEvent timerDead = new ManualResetEvent(false);

    private void Timer_Elapsed(object sender, ElapsedEventArgs e) {
        lock (locker) {
            if (timerDead.WaitOne(0)) return;
            // etc...
        }
    }

    private void StopTimer() {
        lock (locker) {
            timerDead.Set();
            timer.Stop();
        }
    }

考虑将AutoReset属性设置为false。另一种方式是,从捕获异常的内部.NET方法调用已用事件。非常糟糕,您的计时器代码在没有任何诊断的情况下停止运行。我不知道这段历史,但MSFT肯定有另一个团队对这种混乱感到气愤,并编写了System.Threading.Timer。强烈推荐。

计时器似乎不是线程安全的。您必须通过锁定使对它的所有呼叫保持同步。lockobject{}实际上只是一个简单的监视器调用的缩写。

这不会有任何效果,至少如果没有相当多的其他代码。。。此外,这将是一个糟糕的同步机制选择。这实际上不会阻止上述竞争条件。TimeTeCK可以在调用TimeTime.Stest-To的同时发生,并且在此后被触发,在那时,锁将被释放。我从引用的文本中想到,如果事件处理方法在执行中,目标是阻止计时器停止。我认为我的代码可以实现这一点。这可能会导致调用Stop方法后引发已用事件。-使用此选项仍可能发生这种情况。-由于它不检查计时器是否停止…修改,因此已用方法的主体仍将完全执行。这可能不是最好的方法,但至少很简单。哇,计时器真的是阴险的野兽oYes,当你坐在回家的飞机上时,这一切都结束了。气喘吁吁,在登船前进行压力测试。经过一点反思,它似乎在幕后创建了一个线程。计时器,回调确实会吞下异常。基本线程的实现。计时器本身看起来要干净得多,所以我将对此进行详细阅读。嗨,汉斯。很抱歉对这样一个旧线程进行评论,但我认为timerDead.WaitOne实际上应该是timerDead.WaitOne0。一个小的太小,我无法直接编辑,但重要的区别。