26

Task.Delay() 没有按预期运行,或者我不明白它应该做什么。我试图了解TaskC# 中的 s 以及如何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;
            }
        }
    }

当我运行它时,测试会在几毫秒内完成,而不是像我预期的那样在 20 秒内完成。如果我替换Task.Delay()Thread.Sleep(),一切都会按预期工作,并且我会每秒打印一次。我试过添加asyncand awaitinto ChattyWriter(),但它不仅没有增加 1 秒的延迟,而且只打印了一行而不是 20 行。

我究竟做错了什么?

可能有助于描述我在做什么:我的项目使用外部 API(RESTful),在我请求一些任务发生后,我需要轮询 API 以检查任务是否已完成。外部任务可以长时间运行:1-15 分钟。所以我在检查完成之间需要一些延迟。并且可能有许多不同的并发进程与多个外部任务一起执行。我了解,如果我Thread.Sleep()在轮询时使用,同一进程上的其他进程Thread将无缘无故地被阻塞。

4

3 回答 3

48

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异步方法,您最终会陷入死锁。请参阅此处了解更多信息。

于 2013-09-07T11:31:46.580 回答
27

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

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

Task.Delay(1000);

Task.Delay(1000).Wait();
于 2013-09-07T11:22:59.757 回答
2

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;
            }
        }
    }
于 2013-09-07T11:38:03.587 回答