BackgroundWorker 在VSTO中无法工作。

10

我有一个后台工作线程。 在调用该线程之前,我会禁用一个按钮并显示gif动画。 然后我调用runworkerasync方法,并且该方法直到完成都运行正常。 但在“RunWorkerCompleted()”上,我遇到了跨线程错误。 有什么想法为什么会出现这种情况?

    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();
    }
2个回答

24

这似乎是 VSTO 和 BackgroundWorker 的问题。

解决方案在这里

基本上,您需要调用

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

在调用RunWorkerAsync之前。这很好。

为了避免每次实例化对象,您可以在AddIn的主类中拥有一个静态成员并重复使用它。这样一来,您只需要实例化一次。


1
这简直救了我的周末。 - squillman
1
也为我节省了几个小时。 - OfficeAddinDev
1
真的吗?太棒了,但是找到那个解决方案花掉我大部分下午的时间。我需要一杯啤酒! - Mike Gledhill

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属性进行访问,然后通过调用委托重试,以便同步两个线程。这就是方法! - Will Marcouiller

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接