2010-02-10 90 views
11

我正在使用vb.net,並且在我的程序中,當我運行我的背景工具時會使此文本框啓用爲真,因此在我的程序中出現「crossthread operation not invalid」錯誤。我的主子將首先將啓用變爲false,當背景工作者運行時,它會將其恢復爲真,然後退出。爲什麼它給我一個錯誤? FYI:有更多的代碼,但我不想做任何更多的混亂...Crossthread操作無效... - VB.NET

這裏是堆棧跟蹤:

at System.Windows.Forms.Control.get_Handle() 
    at System.Windows.Forms.Control.OnEnabledChanged(EventArgs e) 
    at System.Windows.Forms.Control.set_Enabled(Boolean value) 
    at Helium.Form1.BackgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in C:\Users\Kevin\documents\visual studio 2010\Projects\Helium\Helium\Form1.vb:line 167 
    at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e) 
    at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument) 

,這裏是確切的錯誤消息:

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

有人可以幫我一把!

感謝,

凱文

+0

我認爲該錯誤信息是不言自明。 – 2010-02-10 22:11:53

回答

16

BackgroundWorker類的目的將在GUI保持響應時執行非GUI GUI線程上的工作。除非你設置了Control.CheckForIllegalCrossThreadCallsfalse(你不應該這麼做),或者按照其他答案(我也不會推薦)的建議使用Invoke,否則你會得到非法的跨線程操作異常。

如果你想GUI相關的「東西」的出現BackgroundWorker運行時,我通常建議使用BackgroundWorker.ReportProgress方法和安裝合適的處理器到BackgroundWorker.ProgressChanged事件。如果您想在GUI上發生一些事情,BackgroundWorker已完成,則只需附加您的處理程序即可將GUI更新爲BackgroundWorker.RunWorkerCompleted事件。

+0

+1。在線程運行時,使用'backgroundworker.reportprogress'幫助我更新自己的gui。 – Codemunkeee 2014-10-29 05:24:33

2

不能直接設置是從另一個線程UI線程上的控件的屬性。它可以做到,但這是msdn的一個例子。

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 
+0

所以我應該把textbox1.enabled = true部分放在哪裏? – lab12 2010-02-10 22:24:08

10

您究竟在哪裏設置了Enabled屬性?如果您在DoWork事件處理程序中執行該操作,則此代碼在與創建按鈕不同的線程上運行,這應該會給出您遇到的異常。爲了解決這個問題,你應該使用BeginInvoke。爲方便起見,它可以被包裝成一個方法,像這樣:

Private Sub SetControlEnabled(ByVal ctl As Control, ByVal enabled As Boolean) 
    If ctl.InvokeRequired Then 
     ctl.BeginInvoke(New Action(Of Control, Boolean)(AddressOf SetControlEnabled), ctl, enabled) 
    Else 
     ctl.Enabled = enabled 
    End If 
End Sub 

現在你可以安全地調用這個方法來啓用或從任何線程禁用任何控制:

SetControlEnabled(someButton, False) 
2

Form_Load()請寫下面的代碼部分。你所有的問題都將得到解決。

'## crossed-thread parts will not be controlled by this option... 

System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False 
11

鍵入Form1_Load(或任何你的形式)子下面的代碼:

System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False 

它修復與阻塞跨線程操作的所有問題。

+0

請注意,這個答案是* bad *,正如在[爲了避免在調試過程中出現交叉線程錯誤時將CheckForIllegalCrossThreadCalls設置爲false是否安全](http://stackoverflow.com/questions/13345091/is-it-safe - 只是對設置checkforillegalcrossthreadcalls到假到避免交叉-T)。 **請不要使用它,而是用您的代碼修復問題(即創建合適的代表)。** – cybermonkey 2016-08-14 18:53:30

5

VB.NET中更好的方法是使用Extension它爲跨線程GUI控制調用提供了非常漂亮的代碼。

只需將這行代碼添加到您擁有的任何模塊。

<System.Runtime.CompilerServices.Extension()> _ 
Public Sub Invoke(ByVal control As Control, ByVal action As Action) 
    If control.InvokeRequired Then 
     control.Invoke(New MethodInvoker(Sub() action()), Nothing) 
    Else 
     action.Invoke() 
    End If 
End Sub 

現在你可以寫任何控制調用只有1行長的跨線程控制代碼。

這樣,可以說要清除一個ComboBox,並將其從線程或沒有線程調用你可以用,現在做這個

cboServerList.Invoke(Sub() cboServerList.Items.Clear()) 

要添加後,你的東西清楚了嗎?

cboServerList.Invoke(Sub() cboServerList.Items.Add("Hello World")) 
0

建議使用AutomationPeer。

例如下面的代碼調用當我按下F5鍵時執行按鈕。同樣,如果您希望線程或後臺工作者調用事件或函數,則可以使用自動化對等。在你的情況下,而不是按鈕(我在這裏使用),你可以使用文本框及其適當的屬性來調用。

'Button name=btnExecute 

'Imports System.Windows.Automation.Peers 

'Imports System.Windows.Automation.Provider 

If e.Key = Key.F5 Then 

    Dim peer As New ButtonAutomationPeer(btnExecute) 

    Dim invokeProv As IInvokeProvider = TryCast(peer.GetPattern(PatternInterface.Invoke), IInvokeProvider) 

    invokeProv.Invoke() 

End If 

問候 RV

0
CheckForIllegalCrossThreadCalls = False 
+0

請添加一些附加說明。 – rghome 2016-12-19 15:44:30