使用ContinueWith在Windows服务中重复任务(TPL)

时间:2015-06-30 10:07:51

标签: c# multithreading windows-services task-parallel-library

我有一个Windows服务(用C#编写),它使用任务并行库dll来执行一些并行任务(一次5个任务) 执行任务一次后,我想在正在进行的基础上(每小时)重复相同的任务。调用QueuePeek方法 我是否使用我在下面的代码段中设置的计时器或计数器?

我正在使用计数器设置任务,一旦我达到5,我退出循环,但我也使用.ContinueWith递减计数器,所以我的想法是计数器值将低于5因此循环会继续下去但我的ContinueWith似乎正在主线程上执行,然后循环退出。 使用ContinueWith调用DecrementCounter似乎不起作用

仅供参考:Importer类是使用MEF加载一些库并完成工作

这是我的代码示例:

    private void QueuePeek()
    {            
        var list = SetUpJobs();

        while (taskCounter < 5)
        {
            int j = taskCounter;

            Task task = null;
            task = new Task(() =>
            {
                DoLoad(j);                                        
            });               

            taskCounter += 1;
            tasks[j] = task;
            task.ContinueWith((t) => DecrementTaskCounter());
            task.Start();
            ds.SetJobStatus(1);                               
        }            
        if (taskCounter == 0)
           Console.WriteLine("Completed all tasks.");
    }       

    private void DoLoad(int i)
    {
        ILoader loader;

    DataService.DataService ds = new DataService.DataService();

    Dictionary<int, dynamic> results = ds.AssignRequest(i);

    var data = results.Where(x => x.Key == 2).First();
    int loaderId = (int)data.Value;

    Importer imp = new Importer();

    loader = imp.Run(GetLoaderType(loaderId));

    LoaderProcessor lp = new LoaderProcessor(loader);

    lp.ExecuteLoader();
    }

    private void DecrementTaskCounter()
    {
        Console.WriteLine(string.Format("Decrementing task counter with threadId: {0}",Thread.CurrentThread.ManagedThreadId) );
        taskCounter--;
    }

1 个答案:

答案 0 :(得分:0)

我发现您的代码存在一些问题,可能导致一些难以追踪的错误。首先,如果使用计数器,所有任务可能同时读取和写入,请尝试使用Interlocked。例如:

Interlocked.Increment(ref _taskCounter); // or Interlocked.Decrement(ref _taskCounter);

如果我理解你要完成的任务,我想你想要做的就是使用一个计时器,在每组任务完成后重新安排。

public class Worker
{
    private System.Threading.Timer _timer;
    private int _timeUntilNextCall = 3600000;

    public void Start()
    {
        _timer = new Timer(new TimerCallback(QueuePeek), null, 0, Timeout.Infinite);
    }
    private void QueuePeek(object state)
    {
        int numberOfTasks = 5;

        Task[] tasks = new Task[numberOfTasks];
        for(int i = 0; i < numberOfTasks; i++)
        {
            tasks[i] = new Task(() =>
            {
                DoLoad();
            });
            tasks[i].Start();
        }

        // When all tasks are complete, set to run this method again in x milliseconds
        Task.Factory.ContinueWhenAll(tasks, (t) => { _timer.Change(_timeUntilNextCall, Timeout.Infinite); });
    }

    private void DoLoad() { }
}