背景线程减慢主要 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
我想在一个与主线程不同的线程上,在 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