Asynchronous Programming Control Flow

I read about C # async methods in the last 2 days and, as I understand it, unlike a thread (threadpool.queueuserworkitem()) , calling the async method does not return immediately, and it returns only when the called method gets into wait or finish (or exception)

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 collect, in the above code, AccessTheWebAsync() is called synchronously (i.e., the control does not return immediately when it is called). But in a line named "THREE", the runtime returns control.

My questions:

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

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

  • If AccessTheWebAsync() done something computationally intensive, for example, by running a loop with millions of zillion, the control will only return to the caller when the loop is complete. It is right?

  • Is there a way in an async function to immediately return a control, and then continue with the work in the background thread? (just as if we had called threadpool.queueuserworkitem ())

  • Calls an async method without waiting in it (suppose it's possible) just like calling a non async method?

+6
source share
2 answers

The first is something important: runtime will only return to the caller on await if the expected task is not completed yet.

Question 1: I will provide the MSDN here:

Asynchronous and pending keywords do not create additional threads. Asynchronous methods do not require multithreading because the async method does not start in its thread.

A source

Question 2: It is possible in the implementation of GetStringAsync , but we do not know this, and we also do not need to know this. All we need to know is 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 processor related work to the background thread

You do not 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 will cite again

An asynchronous method usually contains one or more occurrences of the wait statement, but the absence of pending expressions does not cause a compiler error. If the asynchronous method does not use the wait operator to mark the suspension point, the method runs as a synchronous method, despite the async modifier. The compiler generates a warning for such methods.

Source (on the same page as before, only in a different section)

+6
source

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

If there is a synchronization context, and you do not explicitly indicate that you do not want to continue the context (using something like await task.ConfigureAwait(false) ), then the method will resume in the captured context. In user interface applications, this context is a user interface thread, assuming the method is invoked from a user interface thread.

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

Nowhere. Unless you specify otherwise (see above), await returns again to the captured context, which in your case is a UI thread.

If AccessTheWebAsync() done something computationally intensive, for example, by running a loop with millions of zillion, the control will only return to the caller when the loop is complete. Is it correct?

Yes, assuming the loop was before the first "asynchronous" await . ( await can also be β€œsynchronous” if await ed Task already completed.)

Is there a way in an async function to immediately return a control, and then continue with the work in the background thread?

For this you should use Task.Run() .

Calls an async method without waiting in it (suppose it's possible) just like calling a non async method?

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

+3
source

Source: https://habr.com/ru/post/946751/


All Articles