Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Please see the code below, which I have adapted from the following webpage: http://www.codeguru.com/csharp/csharp/introduction-to-async-and-await-keywords-in-c-5.0.htm

Public Class Form1

    Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        Dim program As New Program()
        Await program.PrintSumAsync()
        MsgBox("got here 1")
    End Sub
End Class

Class Program

    Public Async Function PrintSumAsync() As Task
        Dim value1 As Integer = Await GetValueAsync()
        Dim value2 As Integer = Await GetValueAsync()

        Console.WriteLine("Sum of two random numbers is: {0}", value1 + value2)
    End Function

    Private Async Function GetValueAsync() As Task(Of Integer)
        System.Threading.Thread.Sleep(5000)
        Dim random As Integer = ComputeValue()
        Return random
    End Function


    Private Function ComputeValue() As Integer
        MsgBox("got here 2")
        Return New Random().[Next](1, 1000)

    End Function
End Class

I have added a call to Sleep in the GetValueAsync so that it takes a while to finish.

I expected the code to reach msgbox1 (got here 1) before msgbox2 (got here 2). Await seems to stop the main thread. What am I missing? I don't have any experience with the newish await keyword. I upgraded from .net 3.5 to .NET 4.5.2 recently.

Update Based on Davids answer I have edited the code as follows:

Public Class Form1

    Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        test()
        MsgBox("got here 1")
    End Sub

    Public Async Sub test()
        Dim program As New Program()
        Await program.PrintSumAsync()
        'Dim task As Task = program.PrintSumAsync()
        MsgBox("got here 2")
    End Sub
End Class

Class Program

    Public Async Function PrintSumAsync() As Task
        Dim value1 As Integer = Await GetValueAsync()
        Dim value2 As Integer = Await GetValueAsync()

        Console.WriteLine("Sum of two random numbers is: {0}", value1 + value2)
    End Function

    Private Async Function GetValueAsync() As Task(Of Integer)
        Try
            Await Task.Delay(5000)
            Dim random As Integer = ComputeValue()
            Return random
        Catch ex As Exception
            MsgBox(ex.ToString)
        End Try
    End Function


    Private Function ComputeValue() As Integer
        MsgBox("got here 2")
        Return New Random().[Next](1, 1000)
    End Function
End Class

How can I stop the main thread from finishing before message box 2 appears?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
141 views
Welcome To Ask or Share your Answers For Others

1 Answer

Await isn't stopping the main thread, you are:

System.Threading.Thread.Sleep(5000)

There's nothing asynchronous happening in this method:

Private Async Function GetValueAsync() As Task(Of Integer)
    System.Threading.Thread.Sleep(5000)
    Dim random As Integer = ComputeValue()
    Return random
End Function

(I'm surprised the compiler isn't complaining about it. It does with C#.) So even though the method signature and consuming code is decorated with Async and Await keywords, the resulting code isn't actually asynchronous. It can be, however, if you await an asynchronous operation in that method. For example:

Private Async Function GetValueAsync() As Task(Of Integer)
    Await Task.Delay(5000)
    Dim random As Integer = ComputeValue()
    Return random
End Function

This will make the entire stack of operations in question asynchronous, making full use of the new keywords.

Note, however, that the observed results will probably still be the same. Take a look at the top level method:

Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    Dim program As New Program()
    Await program.PrintSumAsync()
    MsgBox("got here 1")
End Sub

The code in that method still isn't going to execute the third line until after the second line has been awaited until completion. The very top level (the UI invoking this handler) will continue without waiting on this method, but this method will wait until its asynchronous operations are complete before it continues.

In order to get the result you're looking for, you would want to capture the Task instead of awaiting it. Something like this:

Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    Dim program As New Program()
    Dim task As Task = program.PrintSumAsync()
    MsgBox("got here 1")
    ' do something with the task object.
    ' await it, provide it with a callback function for when it completes, etc.
End Sub

The Async and Await keywords don't necessarily make a function happen on a new thread. For most intents and purposes, you can very often think of them as simply syntactic shorthand for wrapping part of a method in a ContinueWith() on a Task object. In any given Async method, there needs to be an Await at which to place that ContinueWith(). If there's no Await within it, then the Async method isn't asynchronous.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...