开发者

VB.Net: Understanding the way Application.Run() works

开发者 https://www.devze.com 2023-01-23 19:18 出处:网络
Hans Passant gave me a great answer here, so I thought of asking for more details to try to understand the way Application.Run() works.

Hans Passant gave me a great answer here, so I thought of asking for more details to try to understand the way Application.Run() works.

As far as I understand from the docs, it seems that Application.Run() starts a message loop on the current thread, which in turns enables it to process user input (Is that right?). The overloaded version Application.Run(Form) basically does the same, only it exists when the form closes, and it shows the fo开发者_运维问答rm by default.

That raises a few questions:

  • How would one do to simply call from the Main() sub a function that can communicate with the user to (message boxes and so on) and wait for it to exit?
  • When the message loop is started without a form, how do you launch a new form from this loop, and wait for it to exit? ShowDialog could work, unless you don't want the form to display immediately when launched (eg. if you have a for that's launched minimized to the system tray)
    • Basically, the situation would be as follows: sub `Main` has a list of tasks to execute in 20mn, with a system tray icon telling the user that the program will operate in 20mn. A timer ticks after 20mns, and has to execute say approx. 15 tasks one by one, every time creating an instance of a progress dialog, initially hidden in the taskbar.
    • `ShowDialog` would display the form, which is not wanted; so the way I would do it would be to pass the progress dialog a callback to a function that starts the next task. But that wouldn't exit the first progress form before the second has exited, would it? Which means 15 forms would end up being opened...
    • So the solution may be to invoke (begininvoke?) the callback on the main application loop... Only, I don't know how to do this, because I don't have a form associated with the loop to invoke the callback on...

    I hope my questions are clear (I might confuse many things, sorry),

    Thanks,

    CFP.


    Drop a Timer, ProgressBar and a BackgroundWorker on the form. First thing you'll want to do is to prevent the form from getting visible when the program is started. Paste this code into the form class:

    Protected Overrides Sub SetVisibleCore(ByVal value As Boolean)
        If Not Me.IsHandleCreated Then
            value = False
            Me.CreateHandle
        End If
        MyBase.SetVisibleCore(value)
    End Sub
    

    Use the timer to get the job started. Set its Interval and Enabled properties, add the Tick event handler:

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Me.Show()
        ProgressBar1.Visible = True
        Me.Enabled = False
        BackgroundWorker1.RunWorkerAsync()
    End Sub
    

    That makes the form visible when the job is started and starts the background worker. Set the BGW's WorkerReportsProgress property to True and add the 3 event handlers:

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        '' Do stuff here, call BackgroundWorker1.ReportProgress to update the PB
    End Sub
    
    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        ProgressBar1.Value = e.ProgressPercentage
    End Sub
    
    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        ProgressBar1.Visible = False
        Me.Enabled = True
        Me.Hide()
    End Sub
    

    It is up to you to fill in the code for the DoWork event handler. Have it do those 15 jobs, be sure to call BackgroundWorker1.ReportProgess so that the progress bar gets updated. Which is what the ProgressChanged event handler does. The RunWorkerCompleted event handler hides the form again.

    You can call the Show() method in the context menu item event for the NotifyIcon so that the user can make your form visible again. Call Application.Exit() in the context menu item that allow the user to quit your app. Make sure you disable that when the BGW is running. Or implement a way to cleanly stop the job.

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消