我正在运行Windows服务并使用循环和Thread.Sleep来重复任务,使用计时器方法会更好吗?
如果是,代码示例会很棒
我目前正在使用此代码重复
int curMinute;
int lastMinute = DateTime.Now.AddMinutes(-1).Minute;
while (condition)
{
curMinute = DateTime.Now.Minute;
if (lastMinute < curMinute) {
// do your once-per-minute code here
lastMinute = curMinute;
}
Thread.Sleep(50000); // sleeps for 50 seconds
if (error condition that would break you out of this) {
break; // leaves looping structure
}
}
答案 0 :(得分:43)
计时器是一个更好的主意,IMO。这样,如果要求您的服务停止,它可以非常快速地响应,并且不会再次调用计时器滴答处理程序...如果您正在睡觉,服务管理器将要么等待50秒或者杀死您的线程,这两者都不是非常好。
答案 1 :(得分:31)
class Program
{
static void Main(string[] args)
{
Timer timer = new Timer(new TimerCallback(TimeCallBack),null,1000,50000);
Console.Read();
timer.Dispose();
}
public static void TimeCallBack(object o)
{
curMinute = DateTime.Now.Minute;
if (lastMinute < curMinute) {
// do your once-per-minute code here
lastMinute = curMinute;
}
}
代码可能类似于上面的代码
答案 2 :(得分:11)
重要的是要理解你的代码在结束一个循环和开始下一个循环之间会睡50秒......
计时器将每隔50秒调用一次循环,这不完全相同。
它们都有效,但定时器可能就是你在这里寻找的。 p>
答案 3 :(得分:7)
请注意,调用Sleep()会冻结服务,因此如果请求服务停止,它将不会在Sleep()调用期间做出反应。
答案 4 :(得分:4)
是的,使用Timer可以释放当前正在大部分时间睡眠的线程。计时器也会更准确地每分钟点火,因此您可能不再需要跟踪lastMinute
。
答案 5 :(得分:2)
不完全回答这个问题,而不是
if (error condition that would break you out of this) {
break; // leaves looping structure
}
你应该有
while(!error condition)
另外,我会选择Timer
。
答案 6 :(得分:1)
我需要每分钟开一次线程(see question here),我现在根据收到的答案使用了DispatchTimer
。
答案提供了一些您可能会觉得有用的参考资料。
答案 7 :(得分:1)
我已经使用了两个计时器和Thread.Sleep(x),或者根据具体情况使用它们。
如果我有一段需要反复运行的短代码,我可能会使用计时器。
如果我有一段代码可能需要比延迟计时器更长的时间(例如通过FTP从远程服务器检索文件,我无法控制或知道网络延迟或文件大小/计数),我会在两个周期之间等待一段固定的时间。
两者都有效,但正如前面所指出的那样,他们做了不同的事情。计时器每x毫秒运行一次代码,即使前一个实例尚未完成。 Thread.Sleep(x)在完成每次迭代后等待一段时间,因此每个循环的总延迟总是比睡眠周期更长(可能不会太多)。
答案 8 :(得分:0)
您可以使用其中任何一个。但我认为Sleep()
易于实施,更简洁,更短。
答案 9 :(得分:0)
我也同意,使用计时器是最佳选择。我在过去尝试了类似于你的解决方案,并开始遇到循环失火的问题,我将不得不等待另一个Thread.Sleep()再次触发之前。此外,它确实导致停止服务的各种问题,我会不断有关于它没有响应的错误并且必须关闭。
@ Prashanth的代码应该正是您所需要的。
答案 10 :(得分:-1)
我不得不说睡眠是一个更好的实现,它背后有一个状态机。这仍然可以让您随时控制应用程序,但允许在任何特定时间进行任何响应。这也将处理比“处理循环中的执行时间”
更短的计时器回调例如......
<!-- language: c# -->
public enum State
{
Idle = 0,
Processing = 1,
Stop = 100,
}
public void Run()
{
State state = State.Idle; // could be a member variable, so a service could stop this too
double intervalInSeconds = 60;
System.DateTime nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds);
while (state != State.Stop)
{
switch (state)
{
case State.Idle:
{
if (nextExecution > System.DateTime.Now)
{
state = State.Processing;
}
}
break;
case State.Processing:
{
// do your once-per-minute code here
// if you want it to stop, just set it state to stop.
// if this was a service, you could stop execution by setting state to stop, also
// only time it would not stop is if it was waiting for the process to finish, which you can handle in other ways
state = State.Idle;
nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds);
}
break;
default:
break;
}
System.Threading.Thread.Sleep(1);
}
}