Click here to Skip to main content
15,889,216 members
Please Sign up or sign in to vote.
2.00/5 (1 vote)
See more: , +
Microsoft.VisualStudio.Debugger.Runtime.Main.ThrowCrossThreadMessageException


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.

C#
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());
            }
        }
    }
}
Posted
Updated 28-Jan-13 12:51pm
v2
Comments
Sergey Alexandrovich Kryukov 28-Jan-13 18:05pm    
C#? Tag it.
—SA

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.
 
Share this answer
 
Changed:

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



to:

C#
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;
    }
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900