多线程不同时移动对象

时间:2014-03-23 21:13:26

标签: vb.net multithreading object picturebox

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

以下是代码:

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

1 个答案:

答案 0 :(得分:2)

只有在要执行大量计算时才要在游戏中使用多线程,并且要在不同的CPU核心上进行分发。否则只需使用游戏循环。根据当前游戏时间计算游戏的实际状态和对象的位置。然后更新UI并重复这两个步骤,直到用户停止游戏。

使用多线程来更新UI不会起作用,因为一次只有一个线程可以访问UI。更确切地说,只有UI线程(应用程序启动的线程)可以执行此操作。因此,其他线程必须调用Invoke才能让UI线程更新UI。

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

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

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