首页 > 解决方案 > 无法理解 async 的行为,在 c# 中等待

问题描述

我正在学习 c# 的 await async 功能。但是下面代码的行为让我感到困惑。

public static async Task CreateMultipleTasksAsync() {
    HttpClient client = new HttpClient() {
        MaxResponseContentBufferSize = 1000000
    };
    Task <int> download1 = ProcessUrlAsync("https://msdn.microsoft.com", client);
    Task <int> download2 = ProcessUrlAsync("https://msdn.microsoft.com/library/67w7t67f.aspx", client);
    int length1 = await download1;
    int length2 = await download2;
    Console.WriteLine("Sum is {0}", length1 + length2);
}

public static async Task <int> ProcessUrlAsync(string url, HttpClient client) {
    Console.WriteLine("I am here to process {0}", url);
    var byteArray = await client.GetByteArrayAsync(url);
    Console.WriteLine("processing is completed {0}", url);

    return byteArray.Length;
}

我期待的是在完成 download1 和 download2 后 CreateMultipleAsync() 的最后一行将执行并打印长度总和。问题是最后一行永远不会执行!

标签: c#async-awaittask

解决方案


这是因为您在构造函数中使用了异步方法。从这里删除它。

另外,不要使用async void. 相反,您应该使用async Task

class MultipleAsync
{
    public async Task StartMultiple()
    {
        await CreateMultipleTasksAsync();

    }
    public static async Task CreateMultipleTasksAsync()
    {
        HttpClient client = new HttpClient() { MaxResponseContentBufferSize = 1000000 };
        Task<int> download1 = ProcessUrlAsync("https://msdn.microsoft.com", client);
        Task<int> download2 = ProcessUrlAsync("https://msdn.microsoft.com/library/67w7t67f.aspx", client);
        int length1 = await download1;
        int length2 = await download2;
        Console.WriteLine("Sum is {0}", length1 + length2);
    }
    public static async Task<int> ProcessUrlAsync(string url, HttpClient client)
    {
        Console.WriteLine("I am here to process {0}", url);
        var byteArray = await client.GetByteArrayAsync(url);
        Console.WriteLine("processing is completed {0}", url);

        return byteArray.Length;

    }
}

用法:

MultipleAsync multipleAsync = new MultipleAsync();
await multipleAsync.StartMultiple();

此外,由于您的第二个任务不依赖于第一个任务的结果,您可以并行运行两个任务。第二个任务不会等待第一个任务完成:

HttpClient client = new HttpClient() { MaxResponseContentBufferSize = 1000000 };
Task<int> download1 = ProcessUrlAsync("https://msdn.microsoft.com", client);
Task<int> download2 = ProcessUrlAsync("https://msdn.microsoft.com/library/67w7t67f.aspx", client);
var lengthts = await Task.WhenAll(download1, download2);
Console.WriteLine("Sum is {0}", lengthts.Sum());

推荐阅读