2012-02-21 25 views
1

我有一個項目在VSTO/VB使用BackgroundWorker工作正常。這是一個需要信息網頁的表單。網頁可能需要一段時間,所以我使用BackgroundWorker調用窗體。BackgroundWorker導致錯誤,當沒有啓動項目

然後我有一個添加了BackgroundWorker項目的Excel Addin項目。當我從Excel Addin項目調用表單並使用BackgroundWorker請求網頁時,它會抓取網頁。但是,在完成後,在BackgroundWorker1_RunWorkerCompleted方法期間完成的工作產生了一條錯誤消息:

「跨線程操作無效:從其創建的線程以外的線程訪問的控件'TabPage2'」。

爲什麼從Excel Addin項目調用BackgroundWorker項目時不起作用?

我注意到,當我將BackgroundWorker項目設置爲「啓動項目」時,沒有生成錯誤。它與從Excel Addin項目調用此BackgroundWorker項目有關。

回答

1

編輯:可能是我從非UI線程調用RunWorkerAsync()?

我有一個帶有Ribbon類的Excel Addin項目。該Ribbon1.vb有創建第二個項目的實例,從中BackgroundWorker的將被稱爲一個按鈕點擊方法:

Private Sub Btn_Click(ByVal sender As System.Object, ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) Handles Btn.Click 

    Dim MySecondProject As SecondProject.Form1 = New SecondProject.Form1() 
    MySecondProject.Show() 

End Sub 

MySecondProject然後從自己的按鈕,單擊方法中調用BackgroundWorker的是:

BackgroundWorker1.RunWorkerAsync() 

然後,完成後,BackgroundWorker的正試圖更新MySecondProject標籤:

Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted 

    SuccessLabel.Text = "Success!" 

End Sub 

當MySecondProject是站rtup Project,後臺工作人員跟蹤正確的線程,並在完成後成功更新標籤。使用Excel Addin作爲啓動項目,並在運行時實例化MySecondProject後,backgroundwork似乎失去了正確的線程跟蹤。我應該手動在某處插入Invoke或BeginInvoke以幫助後臺工作人員跟蹤正確的線程更新嗎?

1

所以,事實證明,從功能區啓動的表單啓動的Backgroundworker無法在處理結束時更新控件。我不確定它爲什麼從一個作爲啓動項目啓動的表單工作,但它不能從一個從功能區啓動的表單工作,但事實證明,您需要處理Backgroundworker丟失UI線程的軌跡。

使用MethodInvoker作品,如下面的代碼片段:

Imports System.Windows.Forms 

Public Class Form1 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
     BackgroundWorker1.RunWorkerAsync() 
    End Sub 

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork 
     [do nothing] 
    End Sub 

    Private myString As String = "This is my string" 

    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted 

     If Label1.InvokeRequired Then 
      Dim mi As MethodInvoker = AddressOf UpdateFormText 
      Label1.BeginInvoke(mi) 
     Else 
      Label1.Text = myString 
     End If 

    End Sub 

    Private Sub UpdateFormText() 
     Label1.Text = myString + " (BeginInvoked)" 
    End Sub 

End Class 

在VS2010一個更好的答案,就可以使用內嵌MethodInvoker,而不是第二個功能:

Me.Invoke(CType(Sub() Me.Label1.Text = "This is my string", MethodInvoker))