我知道System.Threading.Timer存在,但我已经有了一个Thread。该线程应始终保持活动状态,但每隔X秒执行一次。测试实现如下所示:
public class MailClass
{
private Action<string> LoggerAction;
private bool _exit;
public MailClass(Action<string> loggerAction)
{
LoggerAction = loggerAction;
}
public void Run()
{
LoggerAction("Run called");
_exit = false;
while(!_exit)
{
Thread.Sleep(TimeSpan.FromSeconds(300));
LoggerAction("Waking up");
}
LoggerAction("Run ended");
}
public void Stop()
{
LoggerAction("Stop called");
_exit = true;
}
}
Run方法执行,然后休眠5分钟,然后再次执行。所以它基本上是一个计时器,每5分钟触发一次+执行动作所需的时间。 (是的,我应该缓存TimeSpan而不是一遍又一遍地重新创建它)
这是正确的方法吗? (在真实应用程序中,Run操作检查Web服务,因此我无法通知我的Thread早先唤醒)
或者我应该使用其他一些概念来获得该线程?我看到的一个问题是Stop的实现。运行线程运行一个循环,每次都检查一个bool,但如果我调用Stop(),我必须等到Sleep Interval结束,这很不方便。
Thread.Abort会很苛刻,所以我猜Thread.Interrupt会以某种方式工作吗? Stop()方法应该允许Run完成它的当前迭代,所以没有硬中止。 AutoResetEvent看起来有点像我需要的东西,但我不完全理解它的作用。
编辑:我认为这种可能的一种方法是添加一个Timer(所以一个单独的线程),然后让Run()结束不使用Thread.Sleep而是使用一些“等到某个对象变化”。然后我会从第二个Thread(5分钟到期时)或Stop操作更改该对象。但那似乎过分了?本质上,Run需要对两个条件做出反应:5分钟到期或某些外部信号(如_exit标志的更改)。有些东西告诉我应该有内置的东西,但也许还有另一个定时器线程专注于每隔5分钟发送一个信号就可以了?
答案 0 :(得分:4)
如果您被迫投票,那么您将被迫进行投票。 Thread.Sleep()
就好了。
但是关于你的中断问题......
我会重新编写您的解决方案以使用Monitor。Wait / Pulse。这确实需要你只在lock(...){}
上保留一个对象,但它让我感觉更清洁。
我说更干净,因为使用Thread.Interrupt()
有效地使用“正常”控制流的异常。停止计时器绝不是意料之外的。但它的设计气味真的(如果存在这样的东西),仅此而已。
快速概述:
//Instead of Thread.Sleep(FIVE_MIN) in Run()...
lock(some_obj)
{
if(Monitor.Wait(some_obj, FIVE_MIN)) //Wait for 5 min (or whatever) or until some_obj is Pulse'd
{
//Got Pulse
}
else
{
//Timeout expired
}
}
//And in Stop()...
_exit = true;
lock(some_obj)
{
Monitor.Pulse(some_obj); //Wakeup the thread in Run() if it's currently Wait'ing
}
答案 1 :(得分:1)
是的,这很酷,你也可以打电话给Thread.Interrupt()来打断睡眠,而不是等待睡眠恢复正常。
如果线程在中断时没有阻塞,它将继续正常处理,直到它再次尝试进入休眠状态。
答案 2 :(得分:1)
是否有理由不能在线程中使用 计时器?你得到了你想要的东西,一个在启动你的方法时永远保持活力的线程,你还可以在任何时候停止计时器而不等待5分钟或中断线程?
(我在线程方面不是很有经验,所以我可能会遗漏一些明显的东西?)
答案 3 :(得分:1)
如果时间间隔很关键,那么请选择窗口中提供的high resolution timers,这样会更准确地触发。
答案 4 :(得分:0)
对我来说似乎是一个很好的解决方案。如果您担心提前停止,可以将睡眠时间设置为更少并保持计数,这样您每5分钟只运行一次实际代码。这样它可以更频繁地检查布尔值并且可以更快地发布。
答案 5 :(得分:0)
你也可以调查一下System.Timers.Timer,但真实地说睡觉并不是一个糟糕的解决方案。