背景线程减慢主要 UI 线程 visual basic

Background Thread slowing Main UI Thread visual basic

我想在一个与主线程不同的线程上,在 Picture Box 中显示一个 gif 文件 2 秒。我是 运行 一个在主线程上移动带有图像的图片框的计时器。

为了测试,我创建了一个图片框并添加了相同的图像,我通过单击按钮启动了后台线程。明显的错误或问题是假设的后台线程减慢了主线程。

Creating and Implementing a Threads 似乎提供了两个选项 BackgroundWorker 和 Task.Run。

我看了这篇 Code Magazine 文章,它提供的选项比我掌握的要多:Code Magazine Article

也看了这篇文章无法将 C# 代码转换为 VB 是的我使用了代码转换器:Stephen Cleary

我的代码是 post 下面为后台线程编辑的,不需要 post 计时器滴答代码。

质疑我遗漏了什么或我做错了什么或者这不可能吗?

Private Sub myThreadMethod()
    'Await
    'Async
    Dim myThread As New Thread(AddressOf myThreadMethod)
    myThread.IsBackground = True

    myThread.Start()
    If Me.InvokeRequired = True Then
        Me.Invoke(Sub()
                      'PbT.Location = New Point(128, 132)
                      PbT.Left -= 1
                      PbT.Top += 2
                  End Sub)
        'If PbT.Bounds.IntersectsWith(btnBot.Bounds) Then
        'TextBox1.Invoke(Sub() TextBox1.Text =
    End If
    If PbT.Location.Y > 500 Then
        PbT.Invoke(Sub() PbT.Location = New Point(350, 230))
        Thread.Sleep(9000)
        myThread.Abort()
    End If

End Sub

问题的答案由 Craig 添加并由 James_Duh

回答
Public Class frmStart

Dim running As Boolean = False
Dim stopWatch As Stopwatch = New Stopwatch

Private Sub frmStart_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    Cursor.Clip = New Rectangle(Me.Location, Me.Size)
    btnLPad.Left = e.X
    btnCPad.Left = e.X + 28
    btnRPad.Left = e.X + 56
End Sub

Private Sub tmrMove_Tick(sender As Object, e As EventArgs) Handles tmrMove.Tick

    Static direction As New Point(0, 4)

    Static endTime As DateTime = DateTime.Now.AddYears(1)
    If DateTime.Now > endTime Then
        PbT.Visible = False
        endTime = DateTime.Now.AddYears(1)
    End If

    If _buttons.All(Function(x) x.Button.Visible = False) Then
        pbOne.Top = 300
        PbT.Visible = False
        tbAns.Visible = True

        stopWatch.Stop()
        Dim ts = stopWatch.Elapsed
        Dim elapsedTime = $"{ts.Minutes:0} Min {ts.Seconds:00} Sec"
        tbAns.Text = elapsedTime

        running = False
        direction = New Point(0, 4)

        tmrMove.Stop()
        MsgBox("You Win")
        stopWatch.Reset()
        '================
        tbAns.Visible = False
        ResetButtons()

    End If

    If pbOne.Bounds.IntersectsWith(btnLPad.Bounds) Then
        direction = New Point(-2, -3)
    End If
    If pbOne.Bounds.IntersectsWith(btnRight.Bounds) Then
        Static spC As Integer = 1
        spC += 1
        direction = If(spC Mod 2 = 0, New Point(-3, 2), New Point(-5, 1))
    End If

    If pbOne.Bounds.IntersectsWith(btnLeft.Bounds) Then
        direction = New Point(4, 2)
    End If

    If pbOne.Bounds.IntersectsWith(btnCPad.Bounds) Then
        direction = New Point(direction.X, -4)
    End If

    If pbOne.Bounds.IntersectsWith(btnRPad.Bounds) Then
        Static spA As Integer = 1
        spA += 1
        direction = If(spA Mod 2 = 0, New Point(1, -5), New Point(-3, -4))
    End If

    If pbOne.Bounds.IntersectsWith(btnTop.Bounds) Then
        Static spE As Integer = 1
        spE += 1
        direction = If(spE Mod 2 = 0, New Point(-3, 2), New Point(4, 2))
    End If

    If pbOne.Bounds.IntersectsWith(btnBot.Bounds) Then
        tmrMove.Stop()
        running = False
        pbOne.Top = 200
        PbT.Visible = False
        MsgBox("Press S to Start")
    End If

    pbOne.Left += direction.X
    pbOne.Top += direction.Y

    For Each x In _buttons
        If pbOne.Bounds.IntersectsWith(x.Button.Bounds) Then
            endTime = DateTime.Now.AddSeconds(2.0)
            x.Button.Visible = False
            x.Button.Location = New Point(350, -30)
            PbT.Location = New Point(x.Location.X + 20, 31)
            PbT.Visible = True
            direction = New Point(3, 3)
        End If
    Next
End Sub
Private Sub frmStart_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown

    If running AndAlso e.KeyCode = Keys.P Then
        tmrMove.Stop()
    End If

    If e.KeyCode = Keys.S Then

        If Not running Then
            stopWatch.Start()
            running = True
        End If

        tmrMove.Interval = 1
        tmrMove.Start()

    End If

End Sub
Public Sub frmStart_KeyPress(sender As Object, e As KeyPressEventArgs) Handles Me.KeyPress
    'Form Property KeyPreview needs to be set to True
    '=================================================

    If Asc(e.KeyChar) = 27 Then

        Const message As String = "YES" & "   Exit Program" + vbCrLf + vbNewLine + "NO" & "     Read Directions"
        Const caption As String = "Exit OR Return"

        Dim result = MessageBox.Show(message, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question)

        If result = DialogResult.Yes Then
            Application.Exit()
        ElseIf result = DialogResult.No Then
            frmInfo.Show()
            Close()
        End If
    End If

End Sub

Private _buttons As (Button As Button, Location As Point)() = Nothing

Private Sub frmStart_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    If _buttons Is Nothing Then
        _buttons =
        {
            (btnB1, New Point(29, 32)),
            (btnB2, New Point(110, 32)),
            (btnB3, New Point(191, 32)),
            (btnB4, New Point(272, 32)),
            (btnB5, New Point(353, 32)),
            (btnB6, New Point(434, 32)),
            (btnB7, New Point(515, 32)),
            (btnB8, New Point(596, 32)),
            (btnB9, New Point(677, 32))
        }
    End If
    ResetButtons()
End Sub

Private Sub ResetButtons()
    For Each x In _buttons
        x.Button.Visible = True
        x.Button.Location = x.Location
    Next
End Sub

结束Class

上面的代码来自 Enigmativity,修复了一些问题。查看他对秒表和播放 gif 的评论。此外,使用他的代码

游戏速度提高了 70%

试图重现这个,但没有看到我自己编写的计时器滴答代码
了解 Breakout 的 GAME 设计将有助于任何尝试遵循 Vectors 步骤的人需要显示 X 秒数的 gif
首先你需要将秒表集成到定时器中
其次,您需要知道何时以秒为单位设置结束时间逻辑要求在 BALL 与 BRICK
相交时发生这种情况 所以我们写了一个叫做 Fire 的函数见下面的代码
不需要每个 BRICK 都有一个 gif,所以现在我们需要将我们唯一的 gif 移动到正确的 BRICK 并让它 运行 X 秒 我们还需要使 gif 可见 为什么你可能会问是否启用和他们 运行 永远可见 仅管理可见性
更容易 您还需要 Timer Tick 方法中的代码,使 gif 在 X 秒后不可见
请原谅我缺少声明变量
pbOne = BALL & btnB1 = BRICK & PbT = 带 gif 的图片框

 Public Function Fire() As Integer
    'Set Stopwatch 5 sec in the future
    nT = CDbl(DateTime.Now.AddSeconds(5).ToString("ss"))
    Return CInt(nT)
End Function


Private Sub tmrMove_Tick(sender As Object, e As EventArgs) Handles tmrMove.Tick

    'nS is Rolling Time
    nS = CDbl(DateTime.Now.ToString("ss"))
    If nS > nT Then
        PbT.Visible = False
    End If

    If pbOne.Bounds.IntersectsWith(btnB1.Bounds) Then
        btnB1.BackColor = Color.Red
        btnB1.Visible = False
        Fire()
        Y = btnB1.Location.Y
        X = btnB1.Location.X
        PbT.Location = New Point(X + 20, Y)
        PbT.Visible = True
        btnB1.Location = New Point(350, -30)
        rndNUM = 8
    End If