Home > database >  How can I do the C# equivalent of await await in Visual Basic
How can I do the C# equivalent of await await in Visual Basic

Time:09-05

I have a VB function which starts a program as a process and waits for it to complete. It passes a return code of zero if okay or 8 if not. The problem is that it blocks the WPF UI thread and can lead to crashes of Not Enough Quota because the thread has been blocked for too long.

So I’m trying to make it run async so the UI thread isn’t blocked. Unfortunately I have many lines of VB code but all the examples on various web sites these days are C# which I don’t program in and I have far too much code to try and learn C# to convert it all.

I’ve tried Await Task.Run which doesn’t accept parameters. I temporarily removed the Pgm parameter and hardcoded the program name and it will then compile and work. I realise I could use global variables instead but that doesn’t seem good practice.

TaskFactory seems to allow parameters but when I await on StartNew control returns immediately because StartNew creates an outer task and an inner task and the Await only waits for the initial outer task. A C# solution I’ve found suggests using Await Await Task but I can’t seem to convert this to a syntax that VB will accept.

Any help would be appreciated on how I can Await for Startit to complete. I'm using .Net 6 and VS 2022 under Windows 10.

Please excuse any formatting errors. This is my first day on Stack Overflow

The code

Class MainWindow
    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
        Call StartitAsync()
        MsgBox("Returned from StartitAsync")
    End Sub

    Private Async Function StartitAsync() As Task(Of Integer)
        Dim Startup As Func(Of String, Integer) = AddressOf Startit
        Dim tf As New TaskFactory
        Dim Rc As Integer = Await tf.StartNew(Startup, "notepad.exe")
        MsgBox("Returned from await of Startit, RC is " & Rc)
        Return Rc
    End Function

    Private Function Startit(Pgm As String) As Integer

        Dim RC As Integer
        Dim Startinfo As New ProcessStartInfo
        MsgBox("Pgm is " & Pgm)
        Startinfo.WindowStyle = ProcessWindowStyle.Maximized ' Display in a maximised window
        Startinfo.FileName = Pgm
        Startinfo.Arguments = ""
        Using PgmProcess As Process = Process.Start(startInfo:=Startinfo) ' Start the program
            PgmProcess.WaitForExit() ' Wait until it ends
            If PgmProcess.HasExited = True Then ' If the process has exited
                RC = PgmProcess.ExitCode ' Save the exit code
            Else
                RC = 8
            End If
        End Using
        Return RC
    End Function

CodePudding user response:

You should use Task.Run instead of Task.Factory.StartNew (or (new TaskFactory()).StartNew). This is true for C# as well as VB.NET.

My VB is extremely rusty, but I believe this is what you're looking for:

Private Async Function StartitAsync() As Task(Of Integer)
  Dim Startup = Function() Startit("notepad.exe")
  Dim Rc As Integer = Await Task.Run(Startup)
  MsgBox("Returned from await of Startit, RC is " & Rc)
  Return Rc
End Function

This uses lambda expressions, which are very useful when using APIs like Task.Run.

Side note: You shouldn't call MsgBox from Startit. Since Task.Run executes Startit on the thread pool, it shouldn't access any UI elements (or do things like show message boxes).

  • Related