6

I have been reading about c# async methods in the past 2 days and from what I understand, unlike in a thread (threadpool.queueuserworkitem()), a call to an async method does not return immediately and it only returns when the called method hits an await or complete(or exception)

Please see the following example.

public partial class MainWindow : Window
{
 // . . .
 private async void startButton_Click(object sender, RoutedEventArgs e)
 {
 // ONE
 Task<int> getLengthTask = AccessTheWebAsync();
 // FOUR
 int contentLength = await getLengthTask;
 // SIX
 resultsTextBox.Text +=
 String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
 }
 async Task<int> AccessTheWebAsync()
 {
 // TWO
 HttpClient client = new HttpClient();
 Task<string> getStringTask =
 client.GetStringAsync("http://msdn.microsoft.com");
 // THREE 
 string urlContents = await getStringTask;
 // FIVE
 return urlContents.Length;
 }
} 

From what I gather, in the above code, AccessTheWebAsync() is called synchronously(i.e. control does not return immediately when it is called). But in the line named 'THREE', the runtime will return control.

My questions are:

  1. How does the runtime decide when to use the threadpool or when to run the task in the calling thread? (i.e. execute the code without returning control)

  2. At which points in the above code, new threads (or thread pool) will be used?

  3. If AccessTheWebAsync() did something computationally intensive, like running a loop with a zillion iterations, the control will only return to the caller when the loop is completed. Is that right?

  4. In an async function, is there a way to return the control immediately and then continue doing the work in say a background thread? (just like if we called threadpool.queueuserworkitem())

  5. Is calling an async method without an await in it (assume it s possible) same as calling a non async method?

svick
246k54 gold badges405 silver badges534 bronze badges
asked Jun 7, 2013 at 7:49

2 Answers 2

5

First something important: The runtime will only return to the caller on await if the task to await hasn't completed yet.

Question 1: I'll quote the MSDN here:

The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread.

Source

Question 2: Maybe in the implementation of GetStringAsync but we don't know that and we also don't have to know it. It's enough for us to know that GetStringAsync somehow gets its result without blocking our thread.

Question 3: If the loop is placed before the await keyword, yes.

Question 4: Quote from the same paragraph as before:

You can use Task.Run to move CPU-bound work to a background thread

You don't need the async and await keywords for this. Example:

private Task<int> DoSomethingAsync()
{
 return Task.Run(() =>
 {
 // Do CPU heavy calculation here. It will be executed in the thread pool.
 return 1 + 1;
 });
}

Question 5: I'll quote again

An async method typically contains one or more occurrences of an await operator, but the absence of await expressions doesn’t cause a compiler error. If an async method doesn’t use an await operator to mark a suspension point, the method executes as a synchronous method does, despite the async modifier. The compiler issues a warning for such methods.

Source (same page as before, just a different section)

answered Jun 7, 2013 at 9:01
Sign up to request clarification or add additional context in comments.

Comments

3

How does the runtime decide when to use the threadpool or when to run the task in the calling thread?

If there is a synchronization context and you don't explicitly specify you don't want to continue on the context (by using something like await task.ConfigureAwait(false)), then the method will resume on the captured context. In UI applications, that context is the UI thread, assuming the method is called from the UI thread.

At which points in the above code, new threads (or thread pool) will be used?

Nowhere. Unless you specify otherwise (see above), await resumes back on the captured context, which in your case is the UI thread.

If AccessTheWebAsync() did something computationally intensive, like running a loop with a zillion iterations, the control will only return to the caller when the loop is completed. Is that right?

Yes, assuming the loop was before the first "asynchronous" await. (await can also be "synchronous" if the awaited Task is already completed.)

In an async function, is there a way to return the control immediately and then continue doing the work in say a background thread?

You should use Task.Run() for that.

Is calling an async method without an await in it (assume it s possible) same as calling a non async method?

It is possible and the compiler will warn you that the method will execute completely synchronously.

answered Jun 7, 2013 at 10:58

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.