非重入C#计时器

Oak*_*Oak 10 c# multithreading timer

f()每次都试图调用一个方法t,但如果之前的调用f()尚未完成,请等到它完成.

我已经阅读了一些关于可用计时器的内容,但找不到任何好的方法来做我想要的,除了手动编写所有内容.关于如何实现这一目标的任何帮助都将受到赞赏,但我担心我可能无法找到使用计时器的简单解决方案.

为了澄清,如果t是一秒,并f()运行我在下面写的任意持续时间,那么:

Step  Operation    Time taken
1     wait         1s
2     f()          0.6s
3     wait         0.4s (because f already took 0.6 seconds)
4     f()          10s
5     wait         0s (we're late)
6     f()          0.3s
7     wait         0.7s (we can disregard the debt from step 4)
Run Code Online (Sandbox Code Playgroud)

请注意,此计时器的性质是f()重新进入时不需要安全,并且此处的大小为1的线程池就足够了.

Han*_*ant 12

使用System.Threading.Timer.用一段Timeout.Infinite初始化它,所以它就像一次性计时器.当f()完成时,调用其Change()方法再次为其充电.


Pau*_*ulG 8

您可以使用"全局"级别var(或更可能是同一类中的公共属性f()),如果f()已经在运行,则返回true .

因此,如果f()在一个名为的类中TimedEvent,首先f()要设置的是Runningtrue

这样你的计时器每秒都会触发,然后启动定时事件(如果它还没有运行)
if (!timedEvent.Running) timedEvent.f()

您评论说,f()如果花费的时间超过计时器间隔,则不会立即重复.这是一个公平的观点.我可能会在内部包含逻辑,f()以便Running保持正确.所以它看起来像这样:

public void f(int t) // t is interval in seconds
{
   this.running = true;

   Stopwatch stopWatch = new Stopwatch();
   stopWatch.Start();

   do
   {
       stopwatch.Reset();

       // Do work here

   } while (stopWatch.Elapsed.Seconds > t); // repeat if f() took longer than t

   this.running = false;   
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您这样做,请注意竞争条件。 (2认同)