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

标签 vb.net multithreading begininvoke

汉斯·帕桑特给了我一个很好的答案here ,所以我想询问更多详细信息,以尝试了解 Application.Run() 的工作方式。

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

这提出了一些问题:

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

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

    最佳答案

    在表单上放置一个计时器、进度条和背景工作器。您要做的第一件事是防止程序启动时窗体可见。将此代码粘贴到表单类中:

    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 运行时禁用它。或者实现一种彻底停止工作的方法。

    关于VB.Net:了解 Application.Run() 的工作方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4100510/

    相关文章:

    c# - 多个 Control.BeginInvoke/Invoke 调用会按顺序执行吗?

    vb.net - .NET & CreateObject,COM对象使用谁的内存?

    regex - 取消 KeyUP 事件的处理程序?网络

    c# - 线程等待时持续处理

    java - "Ternary CAS operation"理论上可能吗?

    .net - 每个 BeginInvoke 之后必须跟一个 EndInvoke 吗?

    c# - 创建虚拟 'shredder' 打印机

    mysql - 监控MySQL表中的新数据

    c++ - 使用 Code::Blocks GNU 编译器编译多线程代码

    c# - 在 C# 中做一些工作时显示进度条?