Task.Delay()的行为不符合预期

tra*_*max 19 c# multithreading task-parallel-library

Task.Delay()没有按预期运行,或者说我不理解它应该做什么.我正试图Task在C#中解决问题,以及如何Thread在我的实现中替换s.

我想要做的是这样的事情:

  • 虽然如此
    • 打印一条线
    • 等一下,
    • 如果满足条件,则退出循环,否则保持循环

我已经通过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;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

当我运行它时,测试以毫秒为单位完成,而不是像我期望的那样在20秒内完成.如果我更换Task.Delay()Thread.Sleep(),一切正常,我也得到了一次打印第二.我试过添加asyncawait进入ChattyWriter(),但不仅它没有添加1秒延迟,它只打印一行而不是20行.

我究竟做错了什么?

可能它有助于描述我正在做的事情:我的项目使用外部API(RESTful),在我请求执行某些任务之后,我需要轮询API以检查任务是否已完成.外部任务可以长时间运行:1-15分钟.所以我需要在检查完成之间有一些延迟.并且可能有许多不同的并发进程与多个外部任务一起执行.我明白,如果我Thread.Sleep()在轮询时使用,那么同样的其他进程Thread将被阻止,没有充分的理由.

slf*_*fan 37

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);
           ...
    }
}
Run Code Online (Sandbox Code Playgroud)

你必须以某种方式打断你的调用线程.单元测试将终止,后台线程也将终止.但是如果从UI调用此方法,UI将不会被阻止.

通过调用Wait异步方法,最终会出现死锁.有关更多信息,请参见此处

  • 这可能是因为你的主线程(测试例程)可以继续运行而你看不到其余部分,因为程序终止了.你会从UI按钮启动线程,UI仍然会响应. (2认同)

Cri*_*scu 24

Task.Delay(1000); 创建一个异步任务,该任务将在一秒钟后完成,但当前方法的执行将并行继续.

为了等待任务先完成,您可以替换

Task.Delay(1000);
Run Code Online (Sandbox Code Playgroud)

Task.Delay(1000).Wait();
Run Code Online (Sandbox Code Playgroud)

  • @trailmax但是这会创建一个新任务,一秒钟什么都不做.更好的方法是简单地调用Thread.Sleep(1000). (3认同)
  • Task.Delay 的一个优点是当传递 CancellationToken 时它是可以取消的。 (2认同)