2010-03-15 36 views
8

我有一個後臺工作者。在我調用worker之前,我禁用了一個按鈕並使gif可見。然後我調用runworkerasync方法,它運行良好,直到comleteion。在'RunWorkerCompleted()'我得到一個交叉線程錯誤。任何想法爲什麼?BackgroundWorker不工作在VSTO

private void buttonRun_Click(object sender, EventArgs e) 
    { 
     if (comboBoxFiscalYear.SelectedIndex != -1 && !string.IsNullOrEmpty(textBoxFolderLoc.Text)) 
     { 
      try 
      { 
       u = new UpdateDispositionReports(
        Convert.ToInt32(comboBoxFiscalYear.SelectedItem.ToString()) 
        , textBoxFolderLoc.Text 
        , Properties.Settings.Default.TemplatePath 
        , Properties.Settings.Default.ConnStr); 
       this.buttonRun.Enabled = false; 
       this.pictureBox1.Visible = true; 

       BackgroundWorker bw = new BackgroundWorker(); 
       bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
       bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
       bw.RunWorkerAsync(); 
       //backgroundWorker1.RunWorkerAsync(); 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show("Unable to process.\nError:" + ex.Message, Properties.Settings.Default.AppName); 
      } 
     } 
    } 

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     buttonRun.Enabled = true; 
     pictureBox1.Visible = false; 
    } 

    void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     u.Execute(); 
    } 
+1

請發佈堆棧跟蹤。 – 2010-03-15 18:42:24

回答

2

一些有關VSTO運行同一個線程中控制的後臺工作。不確定。我必須檢查InvokeRequired

private void buttonRun_Click(object sender, EventArgs e) 
    { 
     if (comboBoxFiscalYear.SelectedIndex != -1 && !string.IsNullOrEmpty(textBoxFolderLoc.Text)) 
     { 
      try 
      { 
       u = new UpdateDispositionReports(
        Convert.ToInt32(comboBoxFiscalYear.SelectedItem.ToString()) 
        , textBoxFolderLoc.Text 
        , Properties.Settings.Default.TemplatePath 
        , Properties.Settings.Default.ConnStr); 
       this.buttonRun.Enabled = false; 
       this.pictureBox1.Visible = true; 

       BackgroundWorker bw = new BackgroundWorker(); 
       bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
       bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
       bw.RunWorkerAsync(); 
       //backgroundWorker1.RunWorkerAsync(); 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show("Unable to process.\nError:" + ex.Message, Properties.Settings.Default.AppName); 
      } 
     } 
    } 
    delegate void ReenableRunCallback(); 

    private void ReenableRun() 
    { 
     if (this.buttonRun.InvokeRequired) 
     { 
      ReenableRunCallback r = new ReenableRunCallback(ReenableRun); 
      this.buttonRun.Invoke(r, null); 
     } 
     else 
      this.buttonRun.Enabled = true; 
    } 
    private void HideProgress() 
    { 
     if (this.pictureBox1.InvokeRequired) 
     { 
      ReenableRunCallback r = new ReenableRunCallback(HideProgress); 
      this.pictureBox1.Invoke(r, null); 
     } 
     else 
      this.pictureBox1.Visible = false; 
    } 

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     ReenableRun(); 
     HideProgress(); 
    } 

    void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     u.Execute(); 
    } 
+2

+1您的按鈕最初是從應用程序的第一個和主線程創建的,也稱爲GUI線程。然後,在RunWorkerCompleted上,嘗試訪問從前一個線程創建的按鈕。然後,您需要驗證您的按鈕是否可以使用InvoqueRequired屬性進行訪問,然後按照您所做的那樣重試通過invoed委託,以同步這兩個線程。就是這個方法! – 2010-03-15 19:25:34

18

這似乎是VSTO和BackgroundWorker的問題。

解決方案是here

基本上你需要調用

System.Threading.SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext()); 

你打電話之前RunWorkerAsync。很棒。

爲了避免每次在您的AddIn主類中都有一個靜態成員時實例化對象並重用它。這樣你只能實例化一次。

+1

這節省了我的週末。 – squillman 2012-12-14 17:51:24

+0

也爲我節省了幾個小時。 – OfficeAddinDev 2015-05-06 09:52:14

+0

認真嗎?優秀的提示,但發現解決方案剛剛殺死了我下午的大部分時間。我需要一杯啤酒! – 2015-10-08 13:59:34