1

我对一个非常简单的代码有疑问

Dim temperature As String = SerialPort1.ReadLine.ToString

        If temperature.StartsWith("temp") Then

            templab.Text = temperature.Substring(4, 2) & "°C"
        End If

它给了

Cross-thread operation not valid: Control 'templab' accessed from a thread other than the thread it was created on.

关于设置标签的文本

我确实在互联网上搜索了这个,我找到了一些解决方案,但我的问题不是这个,我过去用 Visual Studio 2008 和 Windows 7 编写了相同的代码,它没有给我任何错误。现在我使用 Windows 8 和 Visual Studio 2012。我如何在不调用的情况下解决这个问题?提前致谢

完整代码:

Public Class Form1


    Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        Dim temperature As String = SerialPort1.ReadLine.ToString

        If temperature.StartsWith("temp") Then

            templab.Text = temperature.Substring(4, 2) & "°C"
        End If
        ' My.Computer.Audio.Play("C:\Users\Chris\Desktop\ROMANTIC MUSIC INSTRUMENTAL, PIANO AND SAXOPHONE.wav", AudioPlayMode.Background)
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        SerialPort1.Open()
    End Sub
End Class
4

2 回答 2

3

您将需要在线程上调用您的方法。首先检查使用

templab.InvokeRequired

创建方法或匿名委托并在控件上调用它。

来自 MSDN

对 Windows 窗体控件进行线程安全调用 查询控件的 InvokeRequired 属性。如果 InvokeRequired 返回 true,则使用对控件进行实际调用的委托调用 Invoke。如果 InvokeRequired 返回 false,则直接调用控件。在下面的代码示例中,线程安全调用在 ThreadProcSafe 方法中实现,该方法由后台线程执行。如果 TextBox 控件的 InvokeRequired 返回 true,则 ThreadProcSafe 方法会创建一个 SetTextCallback 实例并将其传递给窗体的 Invoke 方法。这会导致在创建 TextBox 控件的线程上调用 SetText 方法,并且在此线程上下文中直接设置 Text 属性。

' This event handler creates a thread that calls a  
' Windows Forms control in a thread-safe way. 
 Private Sub setTextSafeBtn_Click( _
 ByVal sender As Object, _
 ByVal e As EventArgs) Handles setTextSafeBtn.Click

     Me.demoThread = New Thread( _
     New ThreadStart(AddressOf Me.ThreadProcSafe))

     Me.demoThread.Start()
 End Sub 


' This method is executed on the worker thread and makes 
' a thread-safe call on the TextBox control. 
 Private Sub ThreadProcSafe()
   Me.SetText("This text was set safely.")
 End Sub


' This method demonstrates a pattern for making thread-safe 
' calls on a Windows Forms control.  
' 
' If the calling thread is different from the thread that 
' created the TextBox control, this method creates a 
' SetTextCallback and calls itself asynchronously using the 
' Invoke method. 
' 
' If the calling thread is the same as the thread that created 
' the TextBox control, the Text property is set directly.  

 Private Sub SetText(ByVal [text] As String)

 ' InvokeRequired required compares the thread ID of the 
 ' calling thread to the thread ID of the creating thread. 
 ' If these threads are different, it returns true. 
  If Me.textBox1.InvokeRequired Then 
     Dim d As New SetTextCallback(AddressOf SetText)
     Me.Invoke(d, New Object() {[text]})
 Else 
     Me.textBox1.Text = [text]
 End If 
End Sub

有关示例和参考,请参见此处。

于 2013-04-20T20:31:45.927 回答
0

该异常告诉您您对控件的属性进行了线程间调用...

使用控件的一个要求是不要对它们进行线程间调用

因此,要么调用,要么将用于与控件交互的代码移动到创建控件的线程...

如果您的代码执行时间很长并且会阻塞 UI 线程太久,那么唯一的解决方案是调用 ...

于 2013-04-20T20:32:24.843 回答