2010-03-15 31 views
8

Tôi có nhân viên hỗ trợ. Trước khi tôi gọi người lao động, tôi vô hiệu hóa một nút và tạo hình gif. Sau đó tôi gọi phương thức runworkerasync và nó chạy tốt cho đến khi comleteion. Trên 'RunWorkerCompleted()' tôi nhận được một lỗi chủ đề chéo. Bất kỳ ý tưởng tại sao?BackgroundWorker Không hoạt động trong 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

Vui lòng đăng theo dõi ngăn xếp. –

Trả lời

2

điều gì đó về VSTO chạy nhân viên nền trên cùng một luồng với điều khiển. Không chắc. Tôi phải kiểm tra số 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 Nút của bạn ban đầu được tạo từ chuỗi chủ đề đầu tiên và chính của ứng dụng, cũng được biết như là luồng GUI. Sau đó, trên RunWorkerCompleted, bạn cố gắng truy cập vào nút đã được tạo từ chủ đề trước. Sau đó, bạn cần phải xác minh xem nút của bạn có thể được truy cập với thuộc tính InvoqueRequired không, sau đó thử lại thông qua một đại biểu được lập hóa đơn như bạn đã làm, điều này để đồng bộ hóa cả hai luồng. Đó là cách! –

18

Có vẻ như đó là vấn đề với VSTO và BackgroundWorker.

Giải pháp là here.

Về cơ bản bạn cần phải gọi

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

trước khi bạn gọi RunWorkerAsync. Hoạt động tuyệt vời.

Để tránh khởi tạo đối tượng mỗi lần bạn có thể có một thành viên tĩnh trong lớp chính của AddIn và sử dụng lại nó. Bằng cách này bạn chỉ khởi tạo một lần.

+1

Điều này vừa lưu cuối tuần của tôi. – squillman

+0

Đã lưu tôi một vài giờ nữa. – OfficeAddinDev

+0

Nghiêm túc? Lời khuyên tuyệt vời, nhưng việc tìm ra giải pháp đó đã giết chết hầu hết buổi chiều của tôi. Tôi cần một ly bia !! –

Các vấn đề liên quan