0

I've read a lot of tutorials with regards to await/async and i've understood that when it comes to await keyword it will go back to the main context then go back to await (when it's finished) and then continue further if there's something after away within async method. I also read that there is something like ConfigureAwait(False) which simply means that with opposite to i've written before when it comes to await it will not go back to main context at this point but will stay here and wll wait on await to be finished and then continue in async method after that will go back to main cotext. So diffrence is it will not go back to main context but wait on await. Correct if i am wrong. Based on that knowledge in first example i should see following result:

After DoStafAsync
Done running the long operation asynchronously.

but when i just simply add ConfigureAwait(False) it should be:

Done running the long operation asynchronously.
After DoStafAsync

as it will not go back to context but will wait and after async method finishes then will go back. Somehow i see the result as in first output. What i am missing?

Public Class Form1

    Sub LongOperation()
        Threading.Thread.Sleep(5000)
    End Sub

    Private Async Function DoStafAsync() As Task
        lblStatus.Text = "Running a long operation asynchronously... (UI thread should be fully responsive)"
        Await Task.Run(Sub()
                           LongOperation()
                       End Sub).ConfigureAwait(False)

        lblStatus.Text = "Done running the long operation asynchronously."
    End Function

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load    
        dfg
        lblStatus.Text = "After DoStafAsync"
    End Sub

    Async Sub Dfg
        Await DoStafAsync
    End Sub

End Class

Additional question: Some people claims that tasks are not creating threads but working on same ui thread. But there are some people claiming that they are and there are also people claiming that sometimes tasks creating threads and sometimes not. What is true here?

  • Eric Lippert has written some **great posts** on this. [Like this one](http://stackoverflow.com/a/10034608/1070452) this one [is epic](http://stackoverflow.com/a/39522149/1070452) – Ňɏssa Pøngjǣrdenlarp Oct 20 '16 at 00:56
  • @Plutonix ok but i still not see problem within my code and for second case tasks are not creating treads then? –  Oct 20 '16 at 01:04

1 Answers1

0

i've understood that when it comes to await keyword it will go back to the main context then go back to await (when it's finished) and then continue further if there's something after away within async method.

I don't think you're using the term "context" the way it's normally used when explaining async code. Check out my async intro blog post, which explains exactly what the context is and how it's used by await.

In particular, "context" does not mean "method or function". It does not determine how or when the code returns to another part of the code.

You may also want to read my MSDN article on async best practices, which explains why you should avoid async void (except for event handlers). If you make Form1_Load an async void and get rid of dfg, then it works as you would expect:

Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load    
  Await DoStafAsync
  lblStatus.Text = "After DoStafAsync"
End Sub

The reason it wasn't working before is because Form1_Load was not waiting for dfg (or DoStafAsync) to complete - it was just firing them off and then proceeding immediately to setting the label text. As I point out in my best practices article, one of the main problems with async void (async sub) is that the calling code cannot determine when it has completed (at least, not easily).

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • hi, i am getting then the error or Await DoStafAsync: Invalid Operation Exception: Additional information: Cross-thread operation not valid: Control 'lblStatus' accessed from a thread other than the thread it was created on. –  Oct 20 '16 at 21:19
  • does it because if i marked as .ConfigureAwait(False) then this line: lblStatus.Text = "Done running the long operation asynchronously." is trying to be called from thread pool right? –  Oct 20 '16 at 23:53
  • so i simply cannot do it when want to use .ConfigureAwait(False) \? –  Oct 21 '16 at 00:09
  • @JimmyJimm: As I explain my [MSDN article on async best practices](https://msdn.microsoft.com/en-us/magazine/jj991977.aspx), you should use `ConfigureAwait(false)` when your method does **not** need to resume on the context (in this case, on the UI thread). Since your method updates UI elements, it **does** need to resume on the UI thread, and thus cannot use `ConfigureAwait(false)`. – Stephen Cleary Oct 21 '16 at 01:27
  • Clear so it just means the code after await will be normally done on UI context unless i mark it ConfigureAwait(false) then code after await will be run on Thread Pool? So if it runs on Thread Pool i cannot refer to UI context like controls right? Is this all i wrote is correct? –  Oct 21 '16 at 11:48
  • Almost. Actually, code after `ConfigureAwait(false)` *might* run on a thread pool thread (if the task is already completed by the time the `await` is evaluated, the method will continue executing synchronously - in the same context). If you have code that *must* run on a thread pool thread, then you would not want to depend on `ConfigureAwait(false)`; you'd use `Task.Run`. – Stephen Cleary Oct 21 '16 at 14:58