3

So I am trying to learn the basics of using 'async' and 'await' in C#, but I am not sure what I am doing wrong here. I am expecting the following output:

Calling DoDownload DoDownload done [...output here...] 

But I don't get the output of the download, and I also expect "done" but that takes a while. Shouldn't that be output immediately? Also, I can't seem to get the string result either. Here is my code:

namespace AsyncTest { class Program { static void Main(string[] args) { Debug.WriteLine("Calling DoDownload"); DoDownloadAsync(); Debug.WriteLine("DoDownload done"); } private static async void DoDownloadAsync() { WebClient w = new WebClient(); string txt = await w.DownloadStringTaskAsync("http://www.google.com/"); Debug.WriteLine(txt); } } } 
2
  • 5
    Never write async void. Your process is exiting before it finishes. You can't do async like this in a console app. Commented Dec 31, 2013 at 23:28
  • @SLaks, async void is not appropriate in this particular scenario (and, indeed, the majority of cases). However, I still object to the use of the word never. It is a valid tool given the right circumstances. Commented Dec 31, 2013 at 23:59

2 Answers 2

6

To get the behavior you want you need to wait for the process to finish before you exit Main(). To be able to tell when your process is done you need to return a Task instead of a void from your function, you should never return void from a async function unless you are working with events.

A re-written version of your program that works correctly would be

class Program { static void Main(string[] args) { Debug.WriteLine("Calling DoDownload"); var downloadTask = DoDownloadAsync(); Debug.WriteLine("DoDownload done"); downloadTask.Wait(); //Waits for the background task to complete before finishing. } private static async Task DoDownloadAsync() { WebClient w = new WebClient(); string txt = await w.DownloadStringTaskAsync("http://www.google.com/"); Debug.WriteLine(txt); } } 

Because you can not await in Main() I had to do the Wait() function instead. If this was a application that had a SynchronizationContext I would do await downloadTask; instead and make the function this was being called from async.

Sign up to request clarification or add additional context in comments.

4 Comments

@PauloMorgado yes it does and if you look at the OP's question that is the behavior he wants to happen.
This comment is working for me ("DoDownload done" is printed before ending the download), but it seems to be taking a while. Shouldn't that be printed immediately, and then it waits for the download?
Should be instant. I would recommend asking a new question with your new code and asking why it is taking so long.
@ToddMenier Please do not edit peoples posts to make that drastic of changes. "DoDownloadDone" printing before the download finishes is the desired result. See the first two comments to this answer and the formatted text block in the OP's post.
3

You are calling DoDownloadAsync() but you don't wait it. So your program going to the next line. But there is another problem, Async methods should return Task or Task<T>, if you return nothing and you want your method will be run asyncronously you should define your method like this:

private static async Task DoDownloadAsync() { WebClient w = new WebClient(); string txt = await w.DownloadStringTaskAsync("http://www.google.com/"); Debug.WriteLine(txt); } 

And in Main method you can't await for DoDownloadAsync, because you can't use await keyword in non-async function, and you can't make Main async. So consider this:

var result = DoDownloadAsync(); Debug.WriteLine("DoDownload done"); result.Wait(); 

3 Comments

Beware that this is almost always a bad idea.
@SLaks why it's a bad idea ?
Yes @SLaks, this reply missed the context that it's a console application.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.