正确使用 await

Properly Using await

在这段代码中我有错误:Code CS4008: Cannot await 'Void'。这是假设从 link 下载 zip 文件然后解压缩的按钮。

private async void button2_Click(object sender, EventArgs e)
{
    string root = @"C:\test";
    //this if directory doesn't exist
    if (!Directory.Exists(root))
    {
        Directory.CreateDirectory(root);
    }

    progressBar1.Value = 0;
    WebClient webcl = new WebClient();
    webcl.DownloadFileCompleted += Webcl_DownloadFileCompleted;
    webcl.DownloadProgressChanged += Webcl_DownloadProgressChanged;
    
    await webcl.DownloadFileAsync(new Uri("https://download1474.mediafire.com/17r5hin4vceg/izkb8vk7pudg5g4/TEST.zip"), @"C:\GTA\TEST.zip");

    string targetfolder = @"C:\test\UNZIPEDFolder";
    string sourceZipFile = @"C:\test\TEST.zip";
    ZipFile.ExtractToDirectory(sourceZipFile, targetfolder);
}

WebClient 具有名为 ..Async 的方法,它们是一种较旧的异步编程风格(称为 EAP),不是您使用 await 寻找的“异步任务模式”(TAP) .使用 await webcl.DownloadFileTaskAsync 代替

大多数情况下,当这些天 classes 升级为异步时,它是使用 TAP 完成的。一些旧的 classes 遵循 EAP(就像“运行 这个方法和一个事件将在方法完成时触发”),也用 ...Async 后缀调用它的方法。微软没有将这些方法用于 TAP 并破坏全世界使用 EAP 的代码库,而是有一个规则,其中任何 class 具有基于 EAP 的异步方法,升级为具有 TAP 方法,应使用 ...TaskAsync 作为 TAP 的方法后缀

当然,如果您习惯于“等待...异步版本”,这会导致问题,因为 EAP 方法并非设计用于等待...如果您得到“无法等待无效”当您调用 await ...Async 时,检查是否有另一个方法称为 ...TaskAsync 并等待它

另一种形式的异步编程(BeginXXX/EndXXX 配对方法)没有遇到这种“后缀冲突”问题

看起来像 WebClient.DownloadFileAsync returns 'void'. This doesn't work with await. To simplify: the 'await' operator works by taking a TaskTask<T> 并“暂停”该方法直到任务完成。

您应该看看是否可以使用更新的 API(例如 HttpClient and GetStreamAsync)重写示例。