无限循环的任务

时间:2014-04-02 06:04:29

标签: task delay infinite-loop async-await

我是C#的新手,我从Delphi那里开始使用它。所以我可能做错了什么。我的应用程序(Windows服务)使任务控制开关状态并计算“开启”时间。我试过使用Task.Delay(x),但似乎我抓住了死锁...... 主要思想是使每个x ms执行无限循环的任务。我不知道我是否可以使用Timer在lambda方法任务中执行部分代码......?

        int TagCnt = DataCtrl.TagList.Count;                     
        stopExec = false;
        if (TagCnt != 0)
        {                
            tasks = new Task[TagCnt];                
            for (int i = 0; i <= TagCnt - 1; i++)
            {                    
                int TempID = i;
                tasks[TempID] = Task.Run(async () => // make threads for parallel read-write tasks // async
                {                                            
                    Random rand = new Random();
                    TimeSpan delay = TimeSpan.FromMilliseconds(rand.Next(1000, 1500))                                              
                    try
                    {
                        while (!stopExec)
                        {                               
                        cToken.ThrowIfCancellationRequested();                          
                        //do basic job here
                        await Task.Delay(delay, cToken);
                        }//while end                            
                    }
                    catch (...)
                    {
                    ...
                    }                                            
                }, cToken);                   
            }

1 个答案:

答案 0 :(得分:2)

这里出了几个问题:

  • 您正在创建的任务会立即完成,在您的情况下Task.Factory.StartNew会因Task<Task> lambda而返回async。要使其按预期工作,请使用Task.Unwrap解包内部任务。另外,请删除TaskCreationOptions.LongRunning,此处您不需要它:

tasks[TempID] = Task.Factory.StartNew(async () => { ...}).Unwrap();

tasks[TempID] = Task.Run(async () => { ...});
  • 此外,默认情况下,Windows服务线程上没有安装同步上下文。因此,await Task.Delay()之后的代码每次都会在新的池线程上执行,您应该为此做好准备。

  • Task.Delay与周期性计时器略有不同。它将延迟执行。使用Stopwatch计算延迟时间:

// beginning of the loop
stopwatch.Reset();
stopwatch.Start();

// the loop body
// ...

// end of the loop
await Task.Delay(Math.Max(500-Stopwatch.ElapsedMilliseconds, 0));