【发布时间】:2016-12-08 00:43:20
【问题描述】:
假设我们将此事件附加到计时器事件处理程序。
private void TimerTick(object sender, ElapsedEventArgs e)
{
if(_gaurd) return;
lock (this) // lock per instance
{
_gaurd = true;
if (!_timer.Enabled) return;
OnTick(); // somewhere inside here timer may pause it self.
_gaurd = false;
}
}
现在有两件事可以暂停这个计时器。一是来自 UI 线程的用户请求,二是可以自行暂停的计时器。
如果计时器自行暂停我们可以保证暂停将在我们继续之前完成。
timer.Stop();
OnPause(); // timer must be paused because OnPause() is not thread safe.
但如果用户请求定时器暂停,请求来自另一个线程,我们不能保证定时器是否完全暂停。
timer.Stop();
OnPause(); // timer event may be still inside OnTick() and may conflict with OnPause()
----------------------------------------------- -------------------------------------------------- ------
所以我正在寻找一种方法来使这个线程安全。这是我迄今为止尝试过的,但我不确定这是否适用于所有情况。
它看起来不错,但想确定是否有任何我不知道的地方。或者也许想知道是否有更好的方法使这个进程线程安全。
我试图将用户请求与计时器的内部工作分开。因此我有 两个 暂停计时器的方法。
public class Timer
{
internal void InternalStop() // must be called by timer itself.
{
timer.Pause(); // causes no problem
}
public void Stop() // user request must come here. (if timer call this deadlock happens)
{
InternalStop();
lock (this) // reference of timer
{
// do nothing and wait for OnTick().
}
}
}
这不是实际代码,但行为相同。它应该说明这个类不是线程安全的。 :
public class WorkingArea
{
private List<Worker> _workers;
public void OnTick()
{
foreach(var worker in _workers)
{
worker.Start();
}
if(_workers.TrueForAll(w => w.Ends))
{
PauseTimer();
}
}
public void OnPause() // after timer paused
{
foreach(var Worker in _workers)
{
worker.Stop();
}
}
}
【问题讨论】:
-
我不确定我是否在关注。 谁暂停计时器并不重要,总有可能出现竞争条件。但是,您已经锁定了
Tick方法 - 它应该在任何情况下都可以工作 - 是否暂停。 -
@Enigmativity 我试图提供。你看我最后一堂课不是线程安全的。
Worker.Start();与Worker.Stop();冲突 -
@M.kazemAkhgary - 这不是minimal reproducible example。我应该能够复制、粘贴和运行您的代码以查看您的错误或问题。
标签: c# multithreading timer ui-thread