我正在尝试使用并行任务库来启动许多这样的任务:
var workTasks = _schedules.Where(x => x.Task.Enabled);
_tasks = new Task[workTasks.Count()];
_cancellationTokenSource = new CancellationTokenSource();
_cancellationTokenSource.Token.ThrowIfCancellationRequested();
int i = 0;
foreach (var schedule in _schedules.Where(x => x.Task.Enabled))
{
_log.InfoFormat("Reading task information for task {0}", schedule.Task.Name);
if(!schedule.Task.Enabled)
{
_log.InfoFormat("task {0} disabled.", schedule.Task.Name);
i++;
continue;
}
schedule.Task.ServiceStarted = true;
_tasks[i] = Task.Factory.StartNew(() =>
schedule.Task.Run()
, _cancellationTokenSource.Token);
i++;
_log.InfoFormat("task {0} has been added to the worker threads and has been started.", schedule.Task.Name);
}
我希望这些任务能够睡眠,然后每5分钟唤醒并完成他们的工作,此时我在Schedule对象中使用Thread.Sleep,其Run方法是作为参数传递到StartNew的Action :
_tasks[i] = Task.Factory.StartNew(() =>
schedule.Task.Run()
, _cancellationTokenSource.Token);
我在某处读到Thread.Sleep是一个糟糕的解决方案。任何人都可以推荐更好的方法吗?
答案 0 :(得分:2)
根据我的理解,Thread.Sleep
一般都很糟糕,因为即使没有必要,它也会强行将所有东西都移出记忆。在大多数情况下,这不会是一个大问题,但它可能是一个性能问题。
我习惯使用这个代码段:
new System.Threading.EventWaitHandle(false, EventResetMode.ManualReset).WaitOne(1000);
适合一行,并且不会过于复杂 - 它会创建一个永远不会设置的事件句柄,然后在继续之前等待完整的超时时间。
无论如何,如果你只想尝试每5分钟重复一次,那么更好的方法可能就是使用Timer。如果已经考虑了重复的工作方法,你甚至可以创建一个整齐地包装所有内容的类:
using System.Threading;
using System.Threading.Tasks;
public class WorkRepeater
{
Timer m_Timer;
WorkRepeater(Action workToRepeat, TimeSpan interval)
{
m_Timer = new System.Timers.Timer((double)Interval.Milliseconds);
m_Timer.Elapsed +=
new System.Timers.ElapsedEventHandler((o, ea) => WorkToRepeat());
}
public void Start()
{
m_Timer.Start();
}
public void Stop()
{
m_Timer.Stop();
}
}
答案 1 :(得分:0)
错误的解决方案是Task
。 Task
应该用于短期生活操作,例如asynch IO。如果您想控制任务的生命周期,您应该使用Thread
并尽可能多地休眠,因为Thread
是个体的,但Task
在共享的线程池中旋转。