后台线程减慢主UI线程的视觉基础



我想在图片框中,在主线程之外的另一个线程上显示一张gif,持续2秒。我正在运行一个计时器,它可以移动主线程上带有图像的图片框。

为了测试,我创建了一个图片框并添加了相同的图片,我点击按钮启动了背景线程。明显的错误或问题是假定的后台线程减慢了主线程的速度。

创建和实现线程似乎提供了两个选项BackgroundWorker和Task.Run.

我看了这篇代码杂志文章,它提供了比我所掌握的更多的选择:代码杂志文章

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

我的代码发布在下面的后台线程无需发布计时器刻度代码。

问我错过了什么或做错了什么,或者这是不可能的吗

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

终端类

上述代码来自Enigmatity,并解决了许多问题。查看他对秒表和播放gif的评论。同样,使用他的代码,游戏速度快70%

试图重现这个没有看到你的计时器勾号代码我自己写的
了解Breakout的游戏设计将有助于任何试图遵循Vectors步骤的人需要显示X秒的gif
首先你需要将秒表集成到计时器中
其次你需要知道何时以秒为单位设置结束时间逻辑需要在球与砖块相交
所以我们编写了一个名为Fire的函数,请参阅下面的代码
不需要每个砖块都有一个gif,所以现在我们需要将我们唯一的gif移动到正确的砖块上,并让它运行X秒我们还需要使gif可见为什么你可能会问它们是否永远运行启用和可见只需管理可见性就更容易了
你还需要在Timer Tick中输入代码使gif在X秒后不可见的方法
抱歉我缺少声明性变量
pbOne=BALL&btnB1=砖块&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

最新更新