并行任务建议

时间:2010-09-30 10:52:16

标签: c#-4.0

我正在尝试使用并行任务库来启动许多这样的任务:

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是一个糟糕的解决方案。任何人都可以推荐更好的方法吗?

2 个答案:

答案 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)

错误的解决方案是TaskTask应该用于短期生活操作,例如asynch IO。如果您想控制任务的生命周期,您应该使用Thread并尽可能多地休眠,因为Thread是个体的,但Task在共享的线程池中旋转。