2013-04-20 113 views
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 
+0

上面的代碼給出了t他錯誤,因爲它從與運行templab文本框的UI線程不同的線程訪問UI元素(templab)。你能顯示包含這部分的完整代碼嗎? – Steve 2013-04-20 20:29:34

+0

所以我怎麼能創建標籤在同一個線程的代碼? – 2013-04-20 20:30:35

+0

注意:如果你創建另一個線程控制,主UI線程將當它試圖畫你的形式做一個跨線程調用...... – DarkSquirrel42 2013-04-20 20:33:31

回答

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 

查看here作爲示例和參考。

+0

我以前見過它,但我記得過去我有同樣的代碼並沒有給我那個錯誤。爲什麼id現在不起作用? – 2013-04-20 20:33:23

+1

,因爲現在您的代碼在另一個線程上運行,而不是主處理器的主線程 – DarkSquirrel42 2013-04-20 20:35:25

+0

線程? – 2013-04-20 20:38:50

0

除了告訴你,你有一個跨線程調用控件的屬性...

一個需求與控制工作是不是有跨線程調用他們

所以要麼調用,或將代碼與控件的交互移動到創建控件的線程中...

如果您的代碼執行時間過長,並且會阻止UI線程過長,則唯一的解決方案是調用...