Search code examples
c#asynchronousasync-awaitwebclientvoid

Properly Using await


In this code I have error: Code CS4008: Cannot await 'Void'. This is button that is suppose to download zip file from link and then unzip it.

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);
}

Solution

  • WebClient has methods named ..Async that are an older style of asyncronous programming (known as EAP) that is not the "Task Asyncronous Pattern" (TAP) you're looking for with await. Use await webcl.DownloadFileTaskAsync instead

    Mostly, when classes these days are upgraded to be asyncronous it is done using TAP. Some old classes followed EAP (which is like "run this method and an event will fire when the method completes") that also called its methods with an ...Async suffix. Rather than take those methods for TAP, and break codebases all over the world that used EAP, Microsoft have a rule where any class with EAP based Async methods, that is upgraded to have TAP methods, shall use ...TaskAsync as a method suffix for the TAP ones

    Of course, if you're used to "await the ...Async version" , it causes a problem, because EAP methods aren't designed to be awaited... If you get "cannot await void" when you call await ...Async check to see if there is another methods called ...TaskAsync and await that instead

    The other form of asyncronous programming (the BeginXXX/EndXXX paired methods) didn't suffer from this "colliding suffix" problem