尝试基于计时器滴答事件打开表单时出现线程错误
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() 之前。
我有一个运行可计分前屏幕的程序。我想要一个 运行 基于计时器弹出的视频广告循环。我创建了一个单独的表单来播放视频,并使用计时器打开表单并播放一个视频,然后我递增一个全局变量,关闭表单,然后等待计时器重新打开表单。当计时器试图重新打开表单时,它给我一个线程错误。我对这种级别的编码有些陌生,并且对为什么会出现此错误以及如何解决它感到困惑。我阅读了有关该主题的内容,并认为我大体上理解了这个问题,但似乎找不到合适的代码来让它工作。这是代码(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() 之前。