Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Implement Async - Await Function

I am trying to to implement a serial port interface that waits for the integer return value to be updated. For learning purposes, I have an Async function to return an integer from a process function that has a random time delay. I included the errors I see in the comments. The function seems to not return an Integer, and there is no GetAwaiter.

Private Sub btnSubMain_Click(sender As Object, e As EventArgs) Handles btnSubMain.Click
    Dim Answer As Integer
    Answer = SomeInteger() 'Value of type 'Task(of Integer)' cannot be converted to 'Integer'
End Sub

Public Async Function SomeInteger() As Task(Of Integer)
    Dim exampleInteger As Integer = Await AwaitedprocessAsync()  'Await requires that type 'Integer" 
    '                                                             have a suitable GetAwaiter method
    Return exampleInteger
End Function

Function AwaitedprocessAsync() As Integer
    Dim timeout As Integer = CInt(Rnd() * 100)
    Thread.Sleep(timeout)
    Return 34  'return some test integer
End Function
like image 428
RelicCoder Avatar asked Feb 02 '26 14:02

RelicCoder


1 Answers

I guess the reason you want to use Async / Await is to perform asynchronous processing without blocking the UI. But the way you have set it up looks like it will block the UI anyway. Here is an example which demonstrates how you can call a method without blocking, and with blocking

Private Async Sub btnSubMain_Click(sender As Object, e As EventArgs) Handles btnSubMain.Click
    Dim answer As Integer
    Try
        btnSubMain.Enabled = False
        ' async call, UI continues to run
        answer = Await SomeIntegerAsync()
    Finally
        btnSubMain.Enabled = True
    End Try
    MessageBox.Show(answer.ToString())

    Try
        btnSubMain.Enabled = False
        ' synchronous call, UI is blocked
        answer = SomeInteger()
    Finally
        btnSubMain.Enabled = True
    End Try
    MessageBox.Show(answer.ToString())
End Sub

Function SomeIntegerAsync() As Task(Of Integer)
    Return Task.Run(AddressOf SomeInteger)
End Function

Function SomeInteger() As Integer
    Thread.Sleep(5000)
    Return 34
End Function

The first thing to note is that the UI event handler is marked Async, so the awaiting is done in that method. It will be clear to most that your intent is to allow something to happen without blocking the UI. Since it is marked that way, it must contain Await. I have written two functions, one which returns a task and has Async in the name, and another which just returns the integer, without Async in the name.

I call both in the button click handler. The first call will allow the UI to run smoothly while calling the function. You can check that by moving the window around after clicking. The second calls the function directly and blocks the UI. This is a basic design you can follow.

A comment on your question notes you could use Task.Delay but I think sleeping the thread is a good way to simulate long running code which you don't want to block the UI so it makes sense as a demonstration.

like image 154
djv Avatar answered Feb 04 '26 05:02

djv



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!