VB.NET Marquee Progress Until Process Exits

2019-03-02 09:40发布

问题:

While I have some VBScript experience, this is my first attempt at creating a very simple VB.NET (Windows Forms Application) wrapper for a command line application. Please be kind!

I have a very simple GUI with two buttons that both do an action and I'd like to show a marquee progress bar until the action (read: the process) is complete (read: exits).

The 'save' button does this:

Dim SaveEXE As Process = Process.Start("save.exe", "/whatever /arguments")


From there I'm starting the marquee progress bar:

ProgressBar1.Style = ProgressBarStyle.Marquee
ProgressBar1.MarqueeAnimationSpeed = 60
ProgressBar1.Refresh()


I thought I could use SaveEXE.WaitForExit() but the Marquee starts, then stops in the middle until the process exits. Not very useful for those watching; they'll think it hung.


I thought maybe I could do something like this but that causes my VB.Net app to crash

Do
    ProgressBar1.Style = ProgressBarStyle.Marquee
    ProgressBar1.MarqueeAnimationSpeed = 60
    ProgressBar1.Refresh()
Loop Until SaveEXE.ExitCode = 0
ProgressBar1.MarqueeAnimationSpeed = 60
ProgressBar1.Refresh()


I'm not entirely sure what needs to be done, short of getting some formal training.

回答1:

You can use the new Async/Await Feature of .NET 4.5 for this:

Public Class Form1
    Private Async Sub RunProcess()
        ProgressBar1.Visible = True
        Dim p As Process = Process.Start("C:\test\test.exe")
        Await Task.Run(Sub() p.WaitForExit())
        ProgressBar1.Visible = False
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        RunProcess()
    End Sub
End Class

Note the Async keyword in the declaration of the RunProcess sub and the Await keyword.

You run the WaitForExit in another thread and by using Await the application basically stops at this line as long as the task takes to complete.
This however also keeps your GUI reponsive meanwhile. For the example I just show the progressbar (it is invisible before) and hide it once the task is complete.

This also avoids any Application.DoEvents hocus pocus.