开发者

Parallel Task advice

I am trying to use the parallel task library to kick off a number of tasks like this:

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);
}

I want these tasks to sleep and then wake up every 5 minutes and do their stuff, at the moment I am using Thread.Sleep in the Schedule object whose Run method is the Action that is passed into StartNew as an argument like this:

_tasks[i] = Task.Factory.StartNew(() =>
        schedule.Task.Run()
    , _cancellationTokenSo开发者_如何学Curce.Token);

I read somewhere that Thread.Sleep is a bad solution for this. Can anyone recommend a better approach?


By my understanding, Thread.Sleep is bad generally, because it force-shifts everything out of memory even when that's not necessary. It won't be a big deal in most cases, but it could be a performance issue.

I'm in the habit of using this snippet instead:

new System.Threading.EventWaitHandle(false, EventResetMode.ManualReset).WaitOne(1000);

Fits on one line, and isn't overly complicated -- it creates an event handle that will never be set, and then waits for the full timeout period before continuing.

Anyway, if you're just trying to have something repeat every 5 minutes, a better approach would probably be to use a Timer. You could even make a class to neatly wrap everything if your repeated work methods are already factored out:

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();
    }
}


Bad solution are Tasks here. Task should be used for short living operations, like asynch IO. If you want to control life time of task you should use Thread and sleep as much as you like, because Thread is individual, but Tasks are rotated in thread pool which is shared.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜