【问题标题】:Multi-threading not moving objects at the same time多线程不同时移动对象
【发布时间】:2014-05-01 02:03:47
【问题描述】:

我试图让一个线程同时移动两个图片框,但这不会发生,第一个开始移动,然后当第二个开始移动。我不知道如何让它们同时移动。

代码如下:

Imports System.Threading
Public Class Form1
Private picuser As New PictureBox()
Private y As Integer
Private thread1 As Thread
Private thread2 As Thread
Private thread3 As Thread
Private thread4 As Thread

Public Sub enemy1()
    picUser = New System.Windows.Forms.PictureBox()
    picUser.Visible = True
    picUser.Size = New System.Drawing.Size(32, 32)
    picuser.Location = New System.Drawing.Point(100, 100)
    picuser.BackColor = Color.Purple
    Dim e As New AddControlEventArgs(picuser)

    ' Create EventHandler
    Dim ehnd As New EventHandler(AddressOf AddControl)

    ' Invoke EventHandler with EventArgs (don't need sender as of now)
    thread1 = New Thread(Sub() Me.Invoke(ehnd, Nothing, e))
    thread1.Start()
End Sub

Public Sub enemy2()
    picuser = New System.Windows.Forms.PictureBox()
    picuser.Visible = True
    picuser.Size = New System.Drawing.Size(32, 32)
    picuser.Location = New System.Drawing.Point(150, 100)
    picuser.BackColor = Color.Red
    Dim e As New AddControlEventArgs(picuser)

    ' Create EventHandler
    Dim ehnd As New EventHandler(AddressOf AddControl)

    ' Invoke EventHandler with EventArgs (don't need sender as of now)
    thread2 = New Thread(Sub() Me.Invoke(ehnd, Nothing, e))
    thread2.Start()
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    thread3 = New Thread(AddressOf enemy1)
    thread4 = New Thread(AddressOf enemy2)
    thread3.Start()
    thread4.Start()
End Sub

Private Sub mover(ByVal x As PictureBox)
    For z = 0 To 10
        x.Location = New Point(x.Location.X, x.Location.Y + 10)
        Threading.Thread.Sleep(100)
        Me.Refresh()
    Next
End Sub


Public Class AddControlEventArgs : Inherits EventArgs
    Public Sub New(p_control As Control)
        m_control = p_control
    End Sub
    Private m_control As Control
    Public ReadOnly Property Control As Control
        Get
            Return m_control
        End Get
    End Property
End Class

Private Sub AddControl(sender As Object, e As EventArgs)
    ' Cast EventArgs to your custom EventArgs
    Dim ec As AddControlEventArgs = DirectCast(e, AddControlEventArgs)
    Me.Controls.Add(ec.Control)
    Call mover(ec.Control)
End Sub
End Class

【问题讨论】:

  • 你认为Invoke() 是做什么的?你实际上并没有在你的线程上做任何事情。相反,请使用 WinForms 计时器或Await
  • 我编辑了代码以使用Await,它仍然和我描述的@SLaks完全一样
  • 否;完全摆脱线程并使用Await Task.Delay()

标签: vb.net multithreading object picturebox


【解决方案1】:

仅当您需要执行繁重的计算并希望将其分布在不同的 CPU 内核上时,才可以在游戏中使用多线程。否则只需使用游戏循环。根据当前游戏时间计算游戏的实际状态和物体的位置。然后更新 UI 并重复这两个步骤,直到用户停止游戏。

使用多线程来更新 UI 是行不通的,因为一次只有一个线程可以访问 UI。更准确地说,只有 UI 线程(应用程序启动的线程)才能做到这一点。因此其他线程必须调用Invoke 才能让UI 线程更新UI。

人工智能和物理模拟等复杂计算可能仍需要多线程。在这里我看到了两种可能性:

  1. 游戏循环在每个游戏循环中启动多个线程并等待它们全部完成,然后继续更新 UI。

  2. 线程独立运行,不断更新游戏状态。游戏循环反复读取游戏状态并相应地更新 UI。这里需要在访问时锁定游戏状态(公共资源)。保持锁定时间短,即做大量工作,然后锁定、更新、解锁并继续计算。将游戏状态分成几个可以单独锁定的逻辑部分可能是个好主意。这减少了锁冲突的机会。必须访问多个资源的所有线程必须以相同的顺序访问它们。这有助于避免死锁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 2013-06-01
    • 2014-06-28
    相关资源
    最近更新 更多