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

C# Task.Delay()的行为不符合预期,c#,multithreading,task-parallel-library,C#,Multithreading,Task Parallel Library,Task.Delay()的行为不符合预期,或者说我不理解它应该做什么。我正试图了解C#中的Tasks以及如何在实现中替换Threads 我想做的是这样的: 虽然是真的 打印一行 等一下 如果条件满足,则退出循环,否则继续循环 我已经用线程很好地实现了这一点,但所有的酷孩子都说我应该使用任务,不要碰线程 因此,对于代码,我有以下内容(忽略[Test]——这只是一种方便的尝试方式) 当我运行它时,测试在毫秒内完成,而不是像我预期的那样在20秒内完成。如果我将Task.Delay()替换为Th

Task.Delay()的行为不符合预期,或者说我不理解它应该做什么。我正试图了解C#中的
Task
s以及如何在实现中替换
Thread
s

我想做的是这样的:

  • 虽然是真的
    • 打印一行
    • 等一下
    • 如果条件满足,则退出循环,否则继续循环
我已经用线程很好地实现了这一点,但所有的酷孩子都说我应该使用任务,不要碰线程

因此,对于代码,我有以下内容(忽略
[Test]
——这只是一种方便的尝试方式)

当我运行它时,测试在毫秒内完成,而不是像我预期的那样在20秒内完成。如果我将
Task.Delay()
替换为
Thread.Sleep()
,那么一切都会按预期工作,我每秒会得到一次打印输出。我尝试将
async
wait
添加到
ChattyWriter()
中,但它不仅没有添加1秒延迟,而且只打印了一行而不是20行

我做错了什么

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

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

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

Task.Delay(1000);


Task.Delay
返回必须等待的
Task
对象。否则,将立即执行以下代码。因此,必须将方法声明为
async
。然后您可以等待任务。延迟

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
,最终将导致死锁。有关更多信息,请参阅。

任务。延迟()实际上创建了一个任务,因此您只需等待它

试试这个

        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;
            }
        }
    }

我试过了,它只给了我打印出来的第一行,然后就完成了。这可能是因为你的主线程(测试例程)可以继续运行,而你看不到其余的,因为程序终止了。如果您从UI按钮启动线程,UI仍然会有响应。您在这一点上绝对正确!我已将
Thread.Sleep(20000)
放在测试例程中,并得到了预期结果。@trailmax但这会创建一个在一秒钟内不执行任何操作的新任务。一个更好的方法是简单地调用线程。睡眠(1000)。@ TrILMAX,而我的帖子解释了为什么<代码>任务。Delay < /代码>不起作用,请考虑使用所描述的方法,这更有效。方法之间有主要区别吗?我总是认为
async await
只是编译器的一种语法糖?@Alberto如果我在同一个线程上运行多个任务(根据MSDN,这是可能的),并调用
thread.Sleep()
,这将阻止其他任务。如果我错了,请纠正我。Task.Delay有一个优点,即在传递CancellationToken时它是可取消的。Task.Delay返回任务的主要原因是,您可以调用wait。您的答案与@w0lf的答案相同
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);
           ...
    }
}
        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;
            }
        }
    }