线程安全呼叫

时间:2015-02-20 15:18:29

标签: vb.net multithreading winforms

我有以下代码:

Public Class Form1
Dim ping As New Ping
Dim replyeuw As PingReply
Dim euwthread As Thread
Dim num As Integer = 0
Dim pingms As Integer

Public Sub pingareuw()
    If My.Computer.Network.IsAvailable Then
        replyeuw = ping.Send("prod.euw1.lol.riotgames.com")
        pingms = replyeuw.RoundtripTime
        If replyeuw.Status = IPStatus.Success Then
            FlatLabel3.Text = "EUW PING: " & pingms
        Else
            FlatLabel3.Text = "Nope..."
        End If
        Thread.Sleep(500)
    Else
        MsgBox("Liga a net pah!")
    End If
End Sub
Private Sub FormSkin1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    euwthread = New Thread(AddressOf Me.pingareuw)
    euwthread.Start()
End Sub

我收到了这个错误:

  

跨线程操作无效:控制从另一个线程访问的“FlatLabel3”。

为什么?

2 个答案:

答案 0 :(得分:0)

除了创建它的线程(通常是应用程序的主线程)之外,您不能从Control修改Thread。相反,您可以使用BackgroundWorker

Private bw As BackgroundWorker

Private Sub FormSkin1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    ' create a new Backgroundworker and start it
    bw = New BackgroundWorker
    bw.WorkerReportsProgress = True
    bw.RunWorkerAsync()
End Sub

Private Sub bg_DoWork(sender As Object, args As DoWorkEventArgs) _
                     Handles bg.DoWork

    If My.Computer.Network.IsAvailable Then
        replyeuw = ping.Send("prod.euw1.lol.riotgames.com")
        pingms = replyeuw.RoundtripTime
        If replyeuw.Status = IPStatus.Success Then
            bg.ReportProgress(0, "EUW PING: " & pingms)
        Else
            bg.ReportProgress(0, "Nope...")
        End If
        Thread.Sleep(500)
    Else
        MsgBox("Liga a net pah!")
    End If

End Sub

Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) Handles bg.ProgressChanged 
    ' you can access the control here
    FlatLabel3.Text = e.ToString()
End Sub

答案 1 :(得分:0)

通常,您的表单应用程序被标记为“StaThread”。这意味着“单线程公寓”,这是古老的COM时代的语言。你的表单和它上面的控件都存在于相信中,它们永远不会被任何其他线程作为它们创建的线程调用。

要解决您的问题,您需要在函数中使用函数“InvokeRequired”,这些函数是从另一个线程调用的。

这样做的基本方案是(对不起几乎 - c#语法 - 在VB中相同):

void MaybeCalledFromOtherThread()
{
    if( this.InvokeRequired )
         return this.Invoke(MaybeCalledFromOtherThread) // not exact syntax for Invoke

    // code below only executed from the correct thread.
}

因此,在您的情况下,您最好将一个成员函数添加到您的Forms类,如UpdatePingDisplay(string newText),并使用上面显示的技巧。从您的线程中,您可以通过调用新函数替换标签上的那些直接操作,并且所有操作都应该有效。