【问题标题】:Repeat a task (TPL) in windows service, using ContinueWith使用 ContinueWith 在 Windows 服务中重复任务 (TPL)
【发布时间】:2015-07-27 11:05:13
【问题描述】:

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

我正在使用计数器来设置任务,一旦达到 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--;
    }

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • birken 感谢您的建议,尤其是柜台方面的建议。我喜欢你上面建议的大纲。还找到了一个链接,其中包含另一个示例 task.delay [link]stackoverflow.com/questions/27189750/…
    • 看起来 Task.Delay 在后台使用 System.Threading.Timer 来实现延迟。内置取消功能的额外好处似乎是使用 Task.Delay 的一个很好的理由。确保你在使用任务时有良好的异常处理MSDN,因为它可能有点棘手。
    猜你喜欢
    • 2013-10-04
    • 1970-01-01
    • 1970-01-01
    • 2017-12-03
    • 1970-01-01
    • 2021-02-08
    • 2018-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多