Click here to Skip to main content
11,647,828 members (48,016 online)
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# Threading Exception progress , +
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.

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 28-Jan-13 11:10am
Edited 28-Jan-13 12:51pm
v2
Comments
Sergey Alexandrovich Kryukov at 28-Jan-13 18:05pm
   
C#? Tag it.
—SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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.
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Changed:

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


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;
            }
  Permalink  

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

  Print Answers RSS
0 jyo.net 500
1 F-ES Sitecore 370
2 DamithSL 290
3 CPallini 290
4 OriginalGriff 277
0 OriginalGriff 1,342
1 jyo.net 994
2 DamithSL 971
3 Sergey Alexandrovich Kryukov 873
4 CPallini 845


Advertise | Privacy | Mobile
Web01 | 2.8.150804.4 | Last Updated 29 Jan 2013
Copyright © CodeProject, 1999-2015
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100