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

Repeat a task (TPL) in windows service, using ContinueWith

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

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

仅供参考:导入程序 class 将使用 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--;
    }

我发现您的代码存在一些问题,这些问题可能会导致一些难以追踪的错误。首先,如果使用一个所有任务都可能同时读取和写入的计数器,请尝试使用 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() { }
}