当all立即返回时Async /await

本文关键字:Async await 返回 all | 更新日期: 2023-09-27 18:18:58

我有这个"简单"的测试代码…(不要担心类方法的奇怪用法…)

我试图掌握Task<>的复杂性…我想我对Task<>.Start()/Task<>.Result模式有一点了解(也许因为它更像"旧"的Thread.Start() ?),但一旦我抓住了一些东西(所以我把await关键字扔进去)…然后一切又纠缠在一起:-(

)

为什么我的代码在第一个任务完成后立即返回?为什么不等待Task.WhenAll()呢?

static BigInteger Factorial(BigInteger factor)
{
    BigInteger factorial = 1;
    for (BigInteger i = 1; i <= factor; i++)
    {
        factorial *= i;
    }
    return factorial;
}
private class ChancesToWin
{
    private int _n, _r;
    public ChancesToWin(int n, int r)
    {
        _n = n;
        _r = r;
    }
    private Task<BigInteger> CalculateFactAsync(int value)
    {
        return Task.Factory.StartNew<BigInteger>(() => Factorial(value));
    }
    public async Task<BigInteger> getFactN()
    {
        BigInteger result = await CalculateFactAsync(_n);
        return result;
    }
    public async Task<BigInteger> getFactN_R()
    {
        BigInteger result = await CalculateFactAsync(_n - _r);
        return result;
    }
    public async Task<BigInteger> getFactR()
    {
        BigInteger result = await CalculateFactAsync(_r);
        return result;
    }
}
private async static void TaskBasedChancesToWin_UseClass()
{
    int n = 69000;
    int r = 600;
    List<Task<BigInteger>> tasks = new List<Task<BigInteger>>();
    ChancesToWin ctw = new ChancesToWin(n, r);
    tasks.Add(ctw.getFactN());
    tasks.Add(ctw.getFactN_R());
    tasks.Add(ctw.getFactR());
    // The getFactR() returns first of the other two tasks... and the code exit!
    BigInteger[] results = await Task.WhenAll(tasks);
    // I don't get here !!!!
    BigInteger chances = results[0] / results[1] * results[2];
    //Debug.WriteLine(chances);
}
static void Main(string[] args)
{
    TaskBasedChancesToWin_UseClass();
}

当all立即返回时Async /await

异步方法同步运行,直到第一次等待时,它们将控制权返回给调用方法,通常返回一个代表异步操作其余部分的任务。TaskBasedChancesToWin_UseClass不返回任务,所以调用者不能等待任务完成。这就是为什么你不应该在事件处理程序之外使用async void

由于Main不会在操作完成之前等待应用程序结束。

您通常会等待await,但由于Main不能是异步方法,您可以在TaskBasedChancesToWin_UseClass返回的任务上与Wait同步阻塞:

async static Task TaskBasedChancesToWin_UseClass()
{
    // ...
}
static void Main()
{
    TaskBasedChancesToWin_UseClass().Wait();
}