Task.Delay()的行为不符合预期,或者说我不理解它应该做什么。我试图了解C#中的Task
以及如何在我的实现中替换Thread
。
我想做的是这样的事情:
我已经使用Threads实现了这一点,但是所有很酷的孩子都说我应该使用Task,而不要触摸Thread。
所以对于代码我有这个(忽略[Test]
- 这只是一种方便的尝试方法)
[Test]
public void ChattyTask()
{
var chattyTask = new Task(ChattyWriter);
chattyTask.Start();
chattyTask.Wait();
}
public void ChattyWriter()
{
int count = 0;
while (true)
{
var message = String.Format("Chatty Writer number {0}", count);
Trace.WriteLine(message);
count++;
Task.Delay(1000);
if (count >= 20)
{
break;
}
}
}
当我运行它时,测试以毫秒为单位完成,而不是像我期望的那样在20秒内完成。如果我用Task.Delay()
替换Thread.Sleep()
,一切都按预期工作,我会每秒打印一次。我已尝试将async
和await
添加到ChattyWriter()
,但不仅仅添加了1秒延迟,它只打印了一行而不是20行。
我做错了什么?
可能有助于描述我正在做的事情:我的项目使用外部API(RESTful),在我请求执行某些任务之后,我需要轮询API以检查任务是否已完成。外部任务可以长时间运行:1-15分钟。所以我需要在检查完成之间有一些延迟。并且可能有许多不同的并发进程与多个外部任务一起执行。我理解,如果我在轮询时使用Thread.Sleep()
,那么同一Thread
上的其他进程将被无法正常阻止。
答案 0 :(得分:33)
Task.Delay
返回您必须等待的Task
对象。否则,将立即执行以下代码。因此,您必须将方法声明为async
。然后你可以等待Task.Delay
public async Task ChattyWriter()
{
int count = 0;
while (true)
{
var message = String.Format("Chatty Writer number {0}", count);
Trace.WriteLine(message);
count++;
await Task.Delay(1000);
...
}
}
你必须以某种方式打断你的调用线程。单元测试将终止,后台线程也将终止。但是如果你从UI调用这个方法,UI就不会被阻止。
通过在异步方法上调用Wait
,最终会出现死锁。有关详细信息,请参阅here。
答案 1 :(得分:20)
Task.Delay(1000);
创建一个异步任务,该任务将在一秒钟后完成,但当前方法的执行将并行继续。
为了等待任务先完成,您可以替换
Task.Delay(1000);
与
Task.Delay(1000).Wait();
答案 2 :(得分:1)
Task.Delay()实际上创建了一个任务,所以你只需要等待它。
试试这个
public static void ChattyWriter()
{
int count = 0;
while (true)
{
var message = String.Format("Chatty Writer number {0}", count);
Console.WriteLine(message);
count++;
var t = Task.Delay(1000);
t.Wait();
if (count >= 20)
{
break;
}
}
}