async / await whenall立即返回

时间:2015-10-22 11:49:29

标签: c# .net async-await task-parallel-library

我有这个"简单"测试代码...(不要打扰类方法的奇怪用法......)

我正在努力掌握Task<>错综复杂......我想我对Task<>.Start() / Task<>.Result模式有一点了解(可能因为它更像是&#39; old& #39; 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();
}

1 个答案:

答案 0 :(得分:2)

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

由于Main不等待操作,因此您的应用程序在操作有机会完成之前结束。

您通常会等待await,但由于您Main不能是异步方法,因此可以WaitTaskBasedChancesToWin_UseClass同步阻止async static Task TaskBasedChancesToWin_UseClass() { // ... } static void Main() { TaskBasedChancesToWin_UseClass().Wait(); } : / p>

length