我是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);
}
答案 0 :(得分:2)
这里出了几个问题:
Task.Factory.StartNew
会因Task<Task>
lambda而返回async
。要使其按预期工作,请使用Task.Unwrap
解包内部任务。另外,请删除TaskCreationOptions.LongRunning
,此处您不需要它:
tasks[TempID] = Task.Factory.StartNew(async () => { ...}).Unwrap();
Task.Run
,它会自动解包(more about this):
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));