C#语言相当于ScheduledExecutorService

时间:2014-09-04 14:56:36

标签: java c# multithreading

我正在使用具有C#API的RF阅读器设备。基于其API,您需要手动调用其读取功能来读取/标记卡片。

所以我的解决方法是使用Timer来执行每个' n'秒。

我的问题是Timer连续执行,无论Thread.sleep()是否在其内部调用。

Timer timer = new Timer(TimerCallback, null, 500, 1000); // From main() method

// The action that Timer executes
private void TimerCallback(Object o)
{
     scan(); // Action for reading/badging card
     scand.WaitOne(); // AutoResetEvent(true)
     GC.Collect(); // Force garbage collection
}

Thread.sleep()在scan()内部调用。

在Java中,我使用synchronized()来等待另一个线程调用invoke()。我搜索了一整天,但我看不到与ScheduledExecutorService和synchronized()等效的解决方法。

我希望有一个解决方法可以帮助我尽快解决这个问题。

谢谢!

1 个答案:

答案 0 :(得分:2)

我能找到的最可靠的方法是在回调中重新启动计时器。这样,回调不会在激活时中断。

Timer timer = new Timer(TimerCallback, null, 500, 0); 

private void TimerCallback(Object o)
{
     scan(); 
     scand.WaitOne(); 
     timer.Change(500, 0);
}

timer.Change重新安排计时器。

注意:我在Timer启动时删除了重复。

顺便说一句:我删除了GC.Collect(),因为我认为这种做法很糟糕,在大多数情况下都没用。

此外,您可以在方法开始时获取时间(使用Stopwatch)并计算要传递给timer的所需时间增量。更改:

Timer timer = new Timer(TimerCallback, null, 500, 0);
Stopwatch stopwatch = Stopwatch.StartNew();

private void TimerCallback(Object o)
{
     var entered = stopwatch.ElapsedMilliseconds;
     scan(); 
     scand.WaitOne(); 
     var duration = stopwatch.ElapsedMilliseconds - entered;
     var delay = Math.Max(0, 500 - duration);
     timer.Change(delay, 0);
}

这样,在500毫秒减去执行扫描功能所花费的时间后,将调用回调。设置如下,您可以从扫描中删除睡眠。

代码中双回调的原因可能是当第一个线程仍在执行回调时,计时器在另一个线程上执行回调。

另一种解决方案可能是根本不使用Timer。只需循环并使用秒表计算睡眠时间:

private void Scan()
{
     while(scanning)
     {
         var entered = stopwatch.ElapsedMilliseconds;
         scan(); 
         scand.WaitOne();
         var duration = stopwatch.ElapsedMilliseconds - entered;
         var delay = Math.Max(0, 500 - duration);
         Thread.Sleep(delay);
     }
}

确保在单独的线程上调用此方法(您可以使用任务)