尝试基于计时器滴答事件打开表单时出现线程错误

I am getting a thread error when attempting to open a form based on a timer tick event

我有一个运行可计分前屏幕的程序。我想要一个 运行 基于计时器弹出的视频广告循环。我创建了一个单独的表单来播放视频,并使用计时器打开表单并播放一个视频,然后我递增一个全局变量,关闭表单,然后等待计时器重新打开表单。当计时器试图重新打开表单时,它给我一个线程错误。我对这种级别的编码有些陌生,并且对为什么会出现此错误以及如何解决它感到困惑。我阅读了有关该主题的内容,并认为我大体上理解了这个问题,但似乎找不到合适的代码来让它工作。这是代码(VAds 的全局变量)我已经使用调用过程来解决这个带有图片框的问题,但无法为视频找出同样的东西。提前致谢。

Private Sub PlayAdVideos(sender As Object, e As EventArgs) Handles VideoAds.Click
        On Error Resume Next
        If Application.OpenForms().OfType(Of frmAds).Any Then
            frmVideoAds.Close()
            Play_Ads.Text = "Start Video Advertisement Loop"
            Exit Sub
        Else
            Play_Ads.Text = "Close Video Advertisement Loop"
            Dim Sz As Integer
            If ScreenNo.Text = "" Then
                Sz = 1
            Else
                Sz = ScreenNo.Text
            End If

            Dim screen As Screen
            screen = Screen.AllScreens(Sz)
            frmVideoAds.StartPosition = FormStartPosition.Manual
            frmVideoAds.Location = screen.Bounds.Location + New Point(0, 0)
            frmVideoAds.WindowState = FormWindowState.Maximized
            frmVideoAds.FormBorderStyle = FormBorderStyle.None
            frmVideoAds.TopMost = True
            frmVideoAds.BackColor = Color.Black
            frmVideoAds.Show()
        End If

        For Each foundFile As String In My.Computer.FileSystem.GetFiles("C:\CCHS\VideoAds\")
            VideoAdList.Items.Add(foundFile)
        Next

        If VideoAdList.Items.Count = 0 Then
            Exit Sub
        End If

        Dim TMR2 As New System.Timers.Timer()

        VideoAdNum = VideoAdList.Items.Count - 1

        TMR2.Interval = 10000 'miliseconds
        TMR2.Enabled = True
        TMR2.Start()
        AddHandler TMR2.Elapsed, AddressOf OnTimedEvent

    End Sub

    Public Sub OnTimedEvent(ByVal sender As Object, ByVal e As ElapsedEventArgs)

        If frmVideoAds.InvokeRequired Then
            If VAds = VideoAdNum Then
                VAds = 0
            Else
                VAds = VAds + 1
            End If
            frmVideoAds.Invoke(Sub() frmVideoAds.Show())
        Else
            If VAds = VideoAdNum Then
                VAds = 0
            Else
                VAds = VAds + 1
            End If
            frmVideoAds.Show()

        End If
    End Sub

System.Timers.Timer 经过的事件通常总是在 UI 线程以外的线程上触发。

这意味着您每次在该方法中调用 frmVideoAds.Show() 时都必须调用 frmVideoAds.Invoke。

你的 else 语句应该只需要添加调用,这将使两个执行路径相同,这样你就可以更新整个东西。

 Public Sub OnTimedEvent(ByVal sender As Object, ByVal e As ElapsedEventArgs)
            If VAds = VideoAdNum Then
                VAds = 0
            Else
                VAds = VAds + 1
            End If
            frmVideoAds.Invoke(Sub() frmVideoAds.Show())
    End Sub

这通常会起作用,但在某些情况下,特别是 ActiveX,System.Timers 需要在单线程单元 (STA) 中。它默认为多线程单元 (MTA)。要强制它进入 STA 模式,只需添加

TMR2.SynchronizingObject = Me

就在你的 TM2.Start() 之前。