【问题标题】:VB.Net Updating UI from background threadVB.Net 从后台线程更新 UI
【发布时间】:2012-12-27 07:25:14
【问题描述】:

我正在使用 VB.Net 开发类似项目的调度程序,应用程序从带有 Application.Run() 的“Sub Main”开始,所有程序代码都是一个类中的处理程序,该类在此处创建和启动,

Public Sub Main()
  m_App = New myApp
  m_App.Start()
  Application.Run()
End Sub

在myApp内部,有一个定时器来控制任务的执行,它会为每个任务启动一个线程,当任务完成时,如果检测到错误,我们会尝试显示警报窗口。我们测试了执行线程和主线程之间的两种不同通信方式,以显示警报窗口(frmAlert):

1) 通过在任务对象中添加 pulic 事件,然后在主线程中的函数中添加处理程序

2) 使用委托通知主线程

但是,警报窗口无法显示,也没有报告错误。用IDE调试后发现alert窗口已经显示成功,但是任务线程完成后会关闭。

这是一个简化的任务类(使用两种通信方法进行测试),

Public Class myProcess

    Public Event NotifyEvent()

    Public Delegate Sub NotifyDelegate()
    Private m_NotifyDelegate As NotifyDelegate

    Public Sub SetNotify(ByVal NotifyDelegate As NotifyDelegate)
        m_NotifyDelegate = NotifyDelegate
    End Sub


    Public Sub Execute()
        System.Threading.Thread.Sleep(2000)
        RaiseEvent NotifyEvent()
        If m_NotifyDelegate IsNot Nothing Then m_NotifyDelegate()
    End Sub

End Class

以及主要的应用类

Imports System.Threading

Public Class myApp
    Private WithEvents _Timer As New Windows.Forms.Timer

    Private m_Process As New myProcess


    Public Sub Start()
        AddHandler m_Process.NotifyEvent, AddressOf Me.NotifyEvent
        m_Process.SetNotify(AddressOf NotifyDelegate)
        ProcessTasks()
    End Sub

    Private Sub Timer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles _Timer.Tick
        ProcessTasks()
    End Sub

    Public Sub ProcessTasks()
        _Timer.Enabled = False
        '
        Dim m_Thread = New Thread(AddressOf m_Process.Execute)
        m_Thread.Start()
        '
        _Timer.Interval = 30000
        _Timer.Enabled = True
    End Sub

    Public Sub NotifyEvent()
        frmAlert.Show()
    End Sub

    Public Sub NotifyDelegate()
        frmAlert.Show()
    End Sub

End Class

发现frmalert是通过NotifyEvent或NotifyDelegate显示的,但在Execute结束后立即关闭。

我可以知道我们如何从执行线程中弹出一个警报窗口,该窗口可以一直停留在屏幕上,直到用户关闭它?

提前致谢!

【问题讨论】:

    标签: vb.net multithreading


    【解决方案1】:

    如果您希望主线程在子线程引发和事件时执行任何操作,您需要确保它不会终止。

    Public Sub Start()
        AddHandler m_Process.NotifyEvent, AddressOf Me.NotifyEvent
        m_Process.SetNotify(AddressOf NotifyDelegate)
        ProcessTasks()
    
        Do While True  'You might want to add a boolean condition here to instruct the main program to terminate when you want it to.
            System.Threading.Thread.Sleep(200)
        Loop
    End Sub
    

    这将阻止主线程(程序)结束,因此可用于处理子线程引发的任何事件。注意:您的课程缺少终止条件。

    【讨论】:

    • 感谢您的建议,但是没有必要让myApp.start()保持运行,因为调度器是由定时器控制的,没有定时器的事件,此时应用程序不会结束.应用程序由application.run()启动,它会一直在内存中运行,直到我触发Application.Exit()(它会在真实应用程序的NotifyIcon的ContextMenu中完成,这部分在简化中没有显示上面的示例)。
    • 通过从 myProcess.Execute() 调用 frmAlert.show() 确实显示了警报窗口,但是当 myProcess.Execute() 结束时它被关闭(即后台线程完成)。即使我们让 myApp.Start() 继续运行,结果也是一样的。
    猜你喜欢
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-10
    • 2015-03-20
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多