2011-10-08 111 views
2

出於某種原因,我的應用程序中的後臺線程無法更改我的主窗體上的任何標籤,文本框值等。沒有編譯錯誤,當線程執行任何事情時都不會發生。vb.net - 後臺線程問題

下面是一些示例代碼:

Imports System.Threading 

Public Class Class1 
    Dim tmpThread As System.Threading.Thread 

    Private Sub bgFindThread() 
     Form1.lblStatus.Text = "test" 
    End Sub 

    Public Sub ThreadAction(ByVal Action As String) 
     If Action = "Start" Then 
      tmpThread = New System.Threading.Thread(New System.Threading.ThreadStart(AddressOf bgFindThread)) 
      tmpThread.Start() 
     ElseIf Action = "Abort" Then 
      If tmpThread.IsAlive = True Then tmpThread.Abort() 
     End If 
    End Sub 

End Class 

有人可以讓我知道我做錯了嗎?

回答

0

上面的AFAIK代碼會拋出一個異常IllegalCrossThreadException,這是因爲後臺線程不同於UI線程和後臺嘗試在其他線程上設置值。所以windows窗體檢查每個正常工作的線程。 您可以將Control.CheckForIllegalCrossThreadCalls設置爲false以使其生效。下面

代碼是設置屬性是當不運行從後臺線程

Add into your code 
------------------------------ 
Delegate Sub MyDelegate() 
Private Sub RunMyControl() 
    lblStatus.Text = "test" 
End Sub 

Change your code 
------------------------------ 
Private Sub bgFindThread 
    lblStatus.BeginInvoke (New MyDelegate(AddressOf RunMyControl)) 
End Sub 

方法asyncronsly運行代碼到UI線程。

+2

的execption僅拋出。將CheckForIllegalCrossThreadCalls設置爲false是邪惡的! –

+0

這個答案並沒有解決我的問題,但確實讓我走上了正軌。 – Joe

0

您只能從UI線程訪問UI控件。

我建議閱讀這首:http://www.albahari.com/threading/

+0

這個鏈接一般都很好,但它並不能解釋如何從不同的線程正確更新UI元素。 –

+0

@Konrad得到開始的地方! –

0

正如其他人所說,它是被禁止的(有充分的理由)來更新從非UI線程的UI元素。

的規範解決方案如下:

  • 測試自己是否在UI線程
  • 如果這樣外,請求到UI線程內執行的操作
  • [UI線程內]更新控件。

你的情況:

Private Sub bgFindThread() 
    If lblStatus.InvokeRequired Then 
     lblStatus.Invoke(New Action(AddressOf bgFindThread)) 
     Return 
    End If 

    lblStatus.Text = "test" 
End Sub 

是唯一改變的是在方法的開始保護條款,檢驗我們是否是在UI線程內,如果沒有,請執行在UI線程中返回。

0

您可以使用委託在後臺線程中更新UI控件。

實施例的調試器中運行時

Private Delegate Sub bkgChangeControl(ByVal bSucceed As Boolean) 
Private dlgChangeControl As bkgChangeControl = AddressOf ChangeControl 

Private Sub threadWorker_ChangeControl(ByVal bSucceed As Boolean) 
    Me.Invoke(dlgChangeControl, New Object() {bSucceed}) 
End Sub 
    Private Sub ChangeControl() 
    Me.lable="Changed" 
    End Sub 
     'In your background thread, call threadWorker_ChangeControl.