VB.Net:了解 Application.Run() 的工作方式

发布于 2024-09-30 20:14:30 字数 949 浏览 0 评论 0原文

Hans Passant 在此处给了我一个很好的答案,因此我想询问更多详细信息,以尝试了解应用程序的方式。 Run() 有效。

据我从文档中了解到,似乎 Application.Run() 在当前线程上启动一个消息循环,这反过来又使其能够处理用户输入(对吗?)。重载版本 Application.Run(Form) 的作用基本相同,只是在表单关闭时存在,并且默认显示表单。

这就提出了几个问题:

  • 如何简单地从 Main() 子函数调用一个可以与用户通信(消息框等)并等待其退出的函数?
  • 当消息循环在没有表单的情况下启动时,如何从此循环启动一个新表单,并等待它退出? ShowDialog 可以工作,除非您不希望表单在启动时立即显示(例如,如果您有一个最小化到系统托盘启动的 for)
    • 基本上,情况如下:子 `Main` 有一个要在 20mn 内执行的任务列表,并有一个系统托盘图标告诉用户该程序将在 20mn 内运行。计时器在 20 分钟后计时,并且必须执行大约 20 分钟。 15个任务一一完成,每次都会创建一个进度对话框的实例,最初隐藏在任务栏中。
    • `ShowDialog` 会显示表单,这是不需要的;所以我的方法是将进度对话框传递给启动下一个任务的函数的回调。但这不会在第二个进度表单退出之前退出第一个进度表单,不是吗?这意味着最终将打开 15 个表单...
    • 因此解决方案可能是调用(begininvoke?)主应用程序循环上的回调...只是,我不知道该怎么做,因为我不知道有一个与循环关联的表单来调用回调...

    我希望我的问题很清楚(我可能会混淆很多事情,抱歉),
    谢谢,
    金融理财师。

    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 form 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.

    如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

    扫码二维码加入Web技术交流群

    发布评论

    需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

    评论(1

    寂寞清仓 2024-10-07 20:14:30

    将 Timer、ProgressBar 和 BackgroundWorker 放到表单上。您要做的第一件事是防止程序启动时窗体可见。将此代码粘贴到表单类中:

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

    使用计时器开始作业。设置其 Interval 和 Enabled 属性,添加 Tick 事件处理程序:

    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
    

    这使得表单在作业启动并启动后台工作程序时可见。将 BGW 的 WorkerReportsProgress 属性设置为 True 并添加 3 个事件处理程序:

    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
    

    由您来填写 DoWork 事件处理程序的代码。让它完成这 15 项工作,请务必调用 BackgroundWorker1.ReportProgess,以便更新进度条。这就是 ProgressChanged 事件处理程序的作用。 RunWorkerCompleted 事件处理程序再次隐藏表单。

    您可以在 NotifyIcon 的上下文菜单项事件中调用 Show() 方法,以便用户可以使您的表单再次可见。在上下文菜单项中调用 Application.Exit() ,允许用户退出您的应用程序。确保在 BGW 运行时禁用它。或者实施一种彻底停止工作的方法。

    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.

    ~没有更多了~
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文