【问题标题】:Using Task.Delay() closes program [duplicate]使用 Task.Delay() 关闭程序 [重复]
【发布时间】:2020-09-24 16:12:53
【问题描述】:

我尝试使用 Task.Delay() 但是当程序到达那里时,无论如何它都会自行关闭。例如,在这种情况下,程序甚至无法到达Console.Write("*"); 行,它会关闭。我究竟做错了什么?有什么想法吗?

(示例代码)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Whatever
{
    class Program
    {
        static async Task WriteAsync()
        {
            while (true)
            {
                await Task.Delay(1000);
                Console.Write("*");
            }

        }

        static void Main(string[] args)
        {
            WriteAsync();
        }
    }
}

【问题讨论】:

  • 将其更改为static async void Main(string[] args) 并改用await WriteAsync();
  • 我不想使用await WriteAsync();,因为它是一个无限循环,我希望它与其他异步方法同时运行。
  • 然后写其他异步方法。如果Main 在事件循环中没有任何挂起的任务可以恢复执行,它将立即退出。

标签: c# asynchronous async-await


【解决方案1】:

Patrick Roberts 在问题 cmets 中所说的,让你的 main 方法异步。

知道发生了什么很有帮助,所以我会尝试分解它。

Task.Delay(1000) 返回一个任务,该任务必须在某处等待(确实如此)。

但是,等待 Task.Delay(1000) 的任务由 WriteAsync 返回,并且主要方法没有等待该任务(因此,Task.Delay(1000) 实际上并没有在任何地方等待)。

main 方法运行一个返回任务的方法,然后 - 立即 - 它退出,该任务的工作可能已经开始,但没有什么是 (a) 等待它完成,所以程序以未完成的任务终止.

现在在 main 方法中,您可以拥有WriteAsync().Wait()
但是,由于很多原因,不建议这样做,但主要是因为您正在同步调用异步方法,虽然它可以与这个简单的程序一起使用,但它确实会在您的程序中引入死锁。

相反,将您的主要方法更改为异步。
写异步代码的时候需要async all the way down

    static async Task Main(string[] args)
    {
        await WriteAsync();
    }

问题 因此,如果我在 main 中有许多异步方法,则至少必须等待其中一个,否则程序将在任务运行之前完成

回答不,所有任务都必须等待。

    static async Task Main(string[] args)
    {
        WriteAsync01();
        await WriteAsync02();
    }    

如果WriteAsync02()WriteAsync01() 之前完成,程序将在WriteAsync01() 完成之前终止,这不是您想要的。

    static async Task Main(string[] args)
    {
        await WriteAsync01();
        await WriteAsync02();
    }

这将依次等待两个任务,因此WriteAsync01()WriteAsync01() 开始之前运行完成,这可能不是您想要的。

    static async Task Main(string[] args)
    {
        var task1 = WriteAsync01();
        var task2 = WriteAsync02();
        await task1;
        await task2;
    }

将启动两个任务,但程序将等待两个任务完成后再终止。或者,这与上述相同。

    static async Task Main(string[] args)
    {
        var task1 = WriteAsync01();
        var task2 = WriteAsync02();
        await Task.WhenAll(task1, task2);
    }

【讨论】:

  • 我明白了!谢谢你。因此,如果我在 main 中有许多异步方法,则至少必须等待其中一个,否则程序将在任务运行之前完成。
  • 不,他们都必须等待。您希望程序运行直到所有任务都完成。我会更新我的答案。
  • Nitpick,最后两个块不相同。例如,如果task2 出现异常故障,则第一个块直到task1 完成后才会退出,但第二个块将在task2 出现故障后立即退出。
  • @PatrickRoberts, Fair nitpick :)
【解决方案2】:

由于在Main 中没有等待WriteAsync(),因此程序在调用异步任务后继续,实际上在任务完成之前完成。

【讨论】:

    猜你喜欢
    • 2011-03-17
    • 2021-12-22
    • 1970-01-01
    • 2011-07-12
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 2019-10-03
    • 1970-01-01
    相关资源
    最近更新 更多