【问题标题】:BackgroundWorker Not working in VSTOBackgroundWorker 不在 VSTO 中工作
【发布时间】:2012-09-18 21:23:13
【问题描述】:

我有一个后台工作人员。在调用工人之前,我禁用了一个按钮并使 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();
    }

【问题讨论】:

    标签: c# vsto backgroundworker


    【解决方案1】:

    这似乎是 VSTO 和 BackgroundWorker 的问题。

    解决方案是here

    基本上你需要调用

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

    在您致电RunWorkerAsync 之前。效果很好。

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

    【讨论】:

    • 这只是节省了我的周末。
    • 也为我节省了几个小时。
    • 认真的吗?很好的提示,但找到该解决方案只是扼杀了我下午的大部分时间。我需要啤酒!!
    【解决方案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();
        }
    

    【讨论】:

    • +1 您的按钮最初是从应用程序的第一个主线程(也称为 GUI 线程)创建的。然后,在 RunWorkerCompleted 上,您尝试访问从前一个线程创建的按钮。然后,您需要验证是否可以使用 InvoqueRequired 属性访问您的按钮,然后像您一样通过调用的委托重试,以同步两个线程。就是这样!
    猜你喜欢
    • 2011-07-18
    • 2020-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多