BackgroundWorker在VSTO中不起作用

Chr*_*yes 9 c# vsto backgroundworker

我有一名背景工作者.在我调用worker之前,我禁用了一个按钮并使gif可见.然后我调用runworkerasync方法,它运行正常,直到comleteion.在'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();
    }
Run Code Online (Sandbox Code Playgroud)

Ric*_*ote 22

这似乎是VSTO和BackgroundWorker的问题.

解决方案就在这里.

基本上你需要打电话

System.Threading.SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)

在你打电话之前RunWorkerAsync.效果很好.

为了避免每次在AddIn的主类中都有静态成员并重用它时实例化对象.这样你只需要实例化一次.


Chr*_*yes 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();
    }
Run Code Online (Sandbox Code Playgroud)

  • +1 您的按钮最初是从应用程序的第一个主线程(也称为 GUI 线程)创建的。然后,在 RunWorkerCompleted 上,您尝试访问从上一个线程创建的按钮。然后,您需要验证是否可以使用 InvoqueRequired 属性访问您的按钮,然后像您一样通过调用的委托重试,这可以同步两个线程。就是这个方法! (2认同)