【问题标题】:Proper Way cancel Background Worker in Excel process正确的方法取消Excel进程中的后台工作人员
【发布时间】:2013-12-31 15:12:59
【问题描述】:

给出下面的代码取消后台工作人员的最佳方法是什么,以便 Excel 正确关闭。例如,如果您的用户在 excel 进程的中间关闭了表单。下面的代码工作正常。只是盯着使用后台工作人员,所以只要掌握它并希望以正确的方式去做。基本上,下面的代码将让用户使用复选框选择他们想要导出的列(字段)。 int[] cols 是他们选择的列的对应编号。

*这里是更新的代码。我在循环期间使用了取消和中断的建议以及基本的 bgw msdn 文章。我想不出另一种方法来检查何时退出 Excel,所以我使用了行数。谢谢你的提示。

    private void XLWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        this.XLWorker.ReportProgress(-1);

        xl._Application app = new Microsoft.Office.Interop.Excel.Application();
        xl._Workbook workbook = app.Workbooks.Add(Type.Missing);

        // creating new Excelsheet in workbook 
        xl._Worksheet worksheet = null;

        // get the reference of first sheet. By default its name is Sheet1. 
        // store its reference to worksheet            
        worksheet = workbook.Sheets[1];
        worksheet = workbook.ActiveSheet;

        // changing the name of active sheet 
        worksheet.Name = "User Details";
        worksheet.Cells.Font.Size = "12";

        int headerCounter = 1;
        foreach (int col in _export)
        {
            worksheet.Cells[1, headerCounter] = _form.DataGridResultsSet.Columns[col].HeaderText;
            headerCounter++;
        }

        //Format zip code
        xl.Range rngResult = null;
        xl.Range FindRange = null;

        int rowCount = worksheet.UsedRange.Rows.Count;
        for (int columnIndex = 1; columnIndex <= worksheet.UsedRange.Rows.Count; columnIndex++)
        {
            FindRange = worksheet.UsedRange.Columns[columnIndex];
            rngResult = FindRange.Find("ZipCode", Type.Missing, Type.Missing, Type.Missing, Type.Missing, xl.XlSearchDirection.xlNext, Type.Missing, Type.Missing, Type.Missing);

            if (rngResult != null)
            {
                rngResult.EntireColumn.NumberFormat = "00000";
            }
        }

        //Add rows
        int colCounter = 0;
        int pending = 0;
        for (int i = 0; i < _form.DataGridResultsSet.Rows.Count - 1; i++)
        {
            if ((XLWorker.CancellationPending == true))
            {
                e.Cancel = true;
                break;
            }
            else
            {
                foreach (int col in _export)
                {
                    worksheet.Cells[i + 2, colCounter + 1] = _form.DataGridResultsSet.Rows[i].Cells[col].Value.ToString();
                    colCounter++;
                }
                colCounter = colCounter - _export.Length;
                XLWorker.ReportProgress((i * 100) / _form.DataGridResultsSet.Rows.Count - 1);
            }
            pending = i;
        }
        int cancel = pending + 2;
        if (cancel < _form.DataGridResultsSet.Rows.Count)
        {
            Marshal.FinalReleaseComObject(rngResult);
            Marshal.FinalReleaseComObject(FindRange);
            Marshal.FinalReleaseComObject(worksheet);

            rngResult = null;
            FindRange = null;

            worksheet = null;

            workbook.Close(false, Type.Missing, Type.Missing);

            app.Application.Quit();
            app.Quit();

            Marshal.FinalReleaseComObject(workbook);
            workbook = null;

            Marshal.FinalReleaseComObject(app);
            app = null;

            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
        else
        {
            //Format sheet
            worksheet.Columns.AutoFit();
            worksheet.Cells.HorizontalAlignment = xl.XlHAlign.xlHAlignLeft;
            worksheet.Cells.Font.Size = "11";
            xl.Range rngB = (xl.Range)worksheet.Rows[1];
            rngB.Font.Bold = true;

            //Worker completed
            XLWorker.ReportProgress(100);

            Marshal.FinalReleaseComObject(rngResult);
            Marshal.FinalReleaseComObject(FindRange);
            Marshal.FinalReleaseComObject(rngB);
            Marshal.FinalReleaseComObject(worksheet);
            Marshal.FinalReleaseComObject(workbook);

            rngResult = null;
            FindRange = null;
            rngB = null;
            worksheet = null;
            workbook = null;

            //Sleep unti export is complete
            Thread.Sleep(1000);

            //Show Excel
            app.Visible = true;

            //Cleanup
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    private void XLWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        if (e.ProgressPercentage < 0)
        {
            this.buttonActExport.Text = "Calculating...";
            toolStripProgressBar1.Visible = true;
            toolStripStatusLabel1.Visible = true;
        }
        else if (e.ProgressPercentage != 100)
        {
            this.buttonActExport.Text = ("Exporting: " + e.ProgressPercentage.ToString() + "%");
            toolStripProgressBar1.Value = e.ProgressPercentage;
        }
        else
        {
            this.buttonActExport.Text = "Done";
            toolStripProgressBar1.Value = e.ProgressPercentage;
        }
    }

    private void XLWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if ((e.Cancelled == true))
        {
            this.buttonActExport.Text = "Canceled!";
        }

        else if (!(e.Error == null))
        {
            this.buttonActExport.Text = ("Error: " + e.Error.Message);
        }
        else
        {
            this.buttonActExport.Text = "Done!";
        }
        this.buttonActExport.Text = "Export";
        this.buttonActExport.Enabled = true;
        toolStripProgressBar1.Visible = false;
        toolStripStatusLabel1.Visible = false;
        toolStripProgressBar1.Value = 0;
    }

【问题讨论】:

    标签: c# winforms excel backgroundworker winforms-interop


    【解决方案1】:

    您需要执行“合作取消”,您需要修改您的代码以与取消过程“合作”并优雅地停止它试图做的事情。这需要您在整个代码中检查workerXL.CancellationPending,如果它返回true,您将执行适当的步骤来“取消”操作,例如处理必要的资源并关闭excel实例。

    【讨论】:

    • 感谢您的提示。我也是这么想的。让我试一试。
    • 我几乎明白了。我将 Background Worker 移至 Excel 导出表单,并将所有工作放在 DoWork 中。唯一的小问题是因为 dataGridResults 在父表单上,Excel 进程在该表单关闭之前不会完全关闭。至少,这是我的假设。
    猜你喜欢
    • 1970-01-01
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多