VS2008抛出跨线程消息异常 [英] VS2008 Throw Cross Thread Message Exception

查看:97
本文介绍了VS2008抛出跨线程消息异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Microsoft.VisualStudio.Debugger.Runtime.Main.ThrowCrossThreadMessageException





我创建了一个Excel Add-在Visual Studio 2008 for Excel 2003中(除其他外)根据用户选择清除多个Excel工作表中的对象数据。加载项应该按预期运行,但是,在各种操作上以随机间隔运行将导致Excel崩溃。下面的代码包含一个带有进度条,后台工作程序和打开文件对话框(ofd)的窗体。抛出此异常:Microsoft.VisualStudio.Debugger.Runtime.Main.ThrowCrossThreadMessageException(如果不是很明显)在this.progressbar1.Text的Main()事件期间。我已经尝试了几种不同的方法来解决这个问题,它可能会反映在这个代码片段中 - 也许有人可以告诉我我做错了什么,以及 - 如果添加了任何方法 - 可能是不必要的。 br />




I have created an Excel Add-In in Visual Studio 2008 for Excel 2003 that (among other things) clears object data from multiple excel sheets based on user selection. The add-in runs as it should, however, at random intervals on various actions will cause Excel to crash. The code below contains a windows form with a progress bar, background worker and open file dialog (ofd). This exception gets thrown: Microsoft.VisualStudio.Debugger.Runtime.Main.ThrowCrossThreadMessageException (in case it isn''t obvious) during the Main() event at this.progressbar1.Text. I have tried several different methods to resolve this problem and it may be reflected in this code snippet - perhaps someone could enlighten me as to what I am doing wrong and what - if any of the methods that have been added - may be unnecessary.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Win32;

namespace WindowsFormApplication
{
    public partial class Form3 : Form
    {
        private int highestPercentageReached = 0;
        private bool skipreadonly = true;
        public Form3()
        {
            InitializeComponent();
        }

        private void Form3_Load(object sender, EventArgs e)
        {
            Thread newThread = new Thread(new ThreadStart(main));
            newThread.SetApartmentState(ApartmentState.STA);
            newThread.Start();
        }

    [STAThread]
        private void main()
        {
            if ((bool)Invoke(new ExcelSelectHandler(ExcelSelect)))
            {
                Invoke(new MethodInvoker(this.Show));
                backgroundWorker1.RunWorkerAsync();
            }
            else
            {
                Invoke(new MethodInvoker(this.Close));
            }
        }

        private void Form3_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (Char)Keys.Escape)
            {
                backgroundWorker1.CancelAsync();
            }
        }

    private delegate bool ExcelSelectHandler();
        private bool ExcelSelect()
        {

            Invoke(new MethodInvoker(this.Hide));
            ofd.Title = "Excel Reset";
            ofd.Multiselect = true;
            ofd.FileName = "";
            ofd.Filter = "Excel Files|*.xls;*.xlsx;*.xlt;*.xltx;*.xlsb;*.xlsm;*.xltm";
            DialogResult result = ofd.ShowDialog();
            return result == DialogResult.OK;

        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            DataRemove(worker, e);

        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            MethodInvoker proginvoke = delegate
            {
                progressBar1.Value = e.ProgressPercentage;
            };
            progressBar1.BeginInvoke(proginvoke);
        }



        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else if (e.Cancelled)
            {
                Invoke(new MethodInvoker(this.Close));
            }
            else
            {
                Invoke(new MethodInvoker(this.Close));
            }
        }


        private void DataRemove(BackgroundWorker worker, DoWorkEventArgs e)
        {
            try
            {
                object missing = System.Reflection.Missing.Value;
                int k = ofd.FileNames.Length;
                int l = 0;
                Excel.Application eapp = ThisAddIn.xlApplication;
                Excel.Workbook eawb = eapp.ActiveWorkbook;
                Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
                xlApp.ScreenUpdating = false;
                xlApp.Visible = false;
                Excel.Workbook xlWorkbook;
                foreach (var filename in ofd.FileNames)
                {
                    if (l < k)
                    {
                        if (filename != eawb.FullName)
                        {
                            xlWorkbook = xlApp.Workbooks.Open(ofd.FileNames[l].ToString(), missing, missing, missing, missing, missing, true, missing, missing, missing, true, missing, missing, missing, missing);
                            Excel.Worksheet xlWorksheet = (Excel.Worksheet)xlApp.ActiveSheet;

                            Excel.ListRows xlRows = (Excel.ListRows)xlWorksheet.ListObjects;
                            if (xlWorkbook.ReadOnly)
                            {
                                if (skipreadonly)
                                {
                                    xlWorkbook.Close(false, missing, missing);
                                }
                                else
                                {
                                    Invoke(new MethodInvoker(this.Hide));
                                    if (MessageBox.Show("Excel document '" + ofd.SafeFileNames[l].ToString() + "' is either opened or marked read only and data will not removed from this file.  Do you want to ignore this file and continue removing data?", "Data Remover", MessageBoxButtons.YesNo) == DialogResult.No)
                                    {
                                        Invoke(new MethodInvoker(this.Show));
                                        if (worker.WorkerSupportsCancellation == true)
                                        {
                                            worker.CancelAsync();
                                            xlWorkbook.Close(false, missing, missing);
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        Invoke(new MethodInvoker(this.Show));
                                        xlWorkbook.Close(false, missing, missing);
                                    }
                                }
                            }
                            else
                            {
                                if (xlRows.Count > 0)
                                {
                                    foreach (Excel.ListRow xlRow in xlRows)
                                    {
                                        xlRow.Delete();
                                    }
                                }
                                xlWorkbook.Save();
                                xlWorkbook.Close(true, missing, missing);

                            }
                            Marshal.ReleaseComObject(xlRows);
                            Marshal.ReleaseComObject(xlWorksheet);
                            Marshal.ReleaseComObject(xlWorkbook);
                        }

                        else
                        {
                            Excel.Worksheet exlWorksheet = (Excel.Worksheet)eawb.ActiveSheet;
                            Excel.ListRows xlRows = (Excel.ListRows)exlWorksheet.ListObjects;
                            foreach (Excel.ListRow xlRow in xlRows)
                            {
                                xlRow.Delete();
                            }
                        }
                        l += 1;
                    }

                    if (worker.CancellationPending)
                    {
                        e.Cancel = true;
                        break;
                    }
                    else
                    {
                        int percentComplete = l / k * 100;
                        highestPercentageReached = percentComplete;
                        worker.ReportProgress(percentComplete);
                    }
                }
                xlApp.Quit();

                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
                GC.WaitForPendingFinalizers();

                Marshal.FinalReleaseComObject(xlApp);

            }

            catch (Exception ex)
            {

                MessageBox.Show(ex.ToString());
            }
        }
    }
}

推荐答案

你可以不要对线程中的任何用户界面对象执行任何操作。只应使用UI(启动)线程来执行任何用户界面工作。如果您试图建立某种对话,或者修改表单上的控件,或者更改控件上的属性,甚至在控件上调用方法,或者......,从后台工作者内部,你会收到这条消息。
You can NOT do ANYTHING with any user interface objects from a thread. Only the UI (startup) thread should be used to do any user interface work. If you''re trying to put up a dialog of some kind, or modify a control on a form, or change a property on a control, or even call a method on a control, or ..., from inside the background worker, you''ll get this message.


更改:



Changed:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    MethodInvoker proginvoke = delegate
    {
        progressBar1.Value = e.ProgressPercentage;
    };
    progressBar1.BeginInvoke(proginvoke);
}







to:






to:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    this.SetProgBar(e.ProgressPercentage);
}

delegate void setprogbarhandler(int p);
private void SetProgBar(int p)
{
    if (this.progressBar1.InvokeRequired)
    {
        setprogbarhandler pbarh = new setprogbarhandler(SetProgBar);
        this.Invoke(pbarh, new object[] { p });
    }
    else
    {
        progressBar1.Value = p;
    }


这篇关于VS2008抛出跨线程消息异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆