一个变量有一个值,但抛出一个未设置为对象实例的对象引用

A variable has a value but throws an object reference not set to an instance of an object

我有一个函数可以循环 DataTable 并将其保存为 Excel File 使用 SpreadSheetLight for C#

注意到循环遍历 DataTable 并保存其 Excel File 输出需要时间,具体取决于 DataGrid 有多少单元格、行和列,或者 DataTable 摘自。

在我的函数中使用 BackgroundWorker 之前,函数可以正常执行。唯一没有 BackgroundWorker 的旁注当然是 UI 在代码执行时冻结。通过利用 BackgroundWorker 我知道我可以通过在另一个线程上处理保存功能来消除这个问题。

但是在我的函数中应用 BackgroundWorker 之后,整个保存函数中断了。它抛出一个 Object Reference not set to an instance of an Object 但我调试并跟踪并确保传递的两个变量都包含值,并且不为空。我使用的循环与以前相同,我什至尝试使用 For Loop.

这是我遇到的一个片段。如您所见,下面的 window 显示 cellvalue 变量都包含内容。却抛出空引用。

此外,这是我的函数的完整代码

        public void exportSingleDataGridToExcelFile(DataTable dt) {
            using(var sfd = new SaveFileDialog()) {
                sfd.FileName = string.Format("WIP Monitoring-{0}", DateTime.Now.ToString("MM.dd.yyyy"));
                sfd.Filter = "Excel File (*.xlsx)|*.xlsx";

                if(sfd.ShowDialog() == DialogResult.OK) {
                    clb.Enabled = false;
                    cb.Enabled = false;
                    btn.Visible = false;
                    pb.Visible = true;
                    pb.Value = 50;

                    using(var excel = new SLDocument()) {
                        var style = excel.CreateStyle();
                        style.SetHorizontalAlignment(DocumentFormat.OpenXml.Spreadsheet.HorizontalAlignmentValues.Center);
                        style.SetVerticalAlignment(DocumentFormat.OpenXml.Spreadsheet.VerticalAlignmentValues.Center);

                        var bgw = new BackgroundWorker();
                        bgw.WorkerReportsProgress = true;

                        bgw.DoWork += (ss, ee) => {
                            var worker = ss as BackgroundWorker;

                            var count = (dt.Rows.Count + 1) * dt.Columns.Count;
                            var steps = (double) count / 100;
                            var prog = 0.0;
                            var row = 0;
                            var col = 0;

                            //Get Column Headers
                            foreach(DataColumn dc in dt.Columns) {
                                var cell = string.Format("{0}1", col.getExCol());
                                var value = dc.ColumnName;

                                excel.SetCellValue(cell, value);
                                excel.AutoFitColumn(string.Format("{0}1", col.getExCol()));
                                excel.SetCellStyle(string.Format("{0}1", col.getExCol()), style);

                                prog += steps;
                                worker.ReportProgress(((int) prog * 100));

                                col++;
                            }

                            col = 0;

                            //Get Cell Data
                            foreach(DataRow dr in dt.Rows) {
                                foreach(DataColumn dc in dt.Columns) {
                                    var cell = string.Format("{0}{1}", col.getExCol(), row);
                                    var value = dr[dc].ToString();

                                    excel.SetCellValue(cell, value);
                                    excel.AutoFitColumn(cell, row);
                                    excel.SetCellStyle(cell, style);

                                    prog += steps;
                                    worker.ReportProgress(((int) prog * 100));

                                    col++;
                                }
                                col = 0;
                                row++;
                            }
                        };

                        bgw.ProgressChanged += (ss, ee) => {
                            pb.Value = ee.ProgressPercentage / 100;
                        };

                        bgw.RunWorkerCompleted += (ss, ee) => {
                            try {
                                excel.SaveAs(sfd.FileName);
                                form.Close();
                            } catch(Exception ex) {
                                MessageBox.Show(ex.Message, "Error while saving", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                        };

                        bgw.RunWorkerAsync();
                    }
                }
            }
        }

最初,在我实现 BackgroundWorker.

之前,同样的代码可以工作

希望我能在这里走走。

很可能 excel 中的 SLDocuemnt 实例中的某些东西是 null 当你的后台工作者被执行时。

您正在 using 语句中创建 excel。这意味着在 using 块的末尾, excel 将被释放。但是在该块内,您启动了一个使用此 excel 变量的后台工作程序。

后台工作程序运行的时间肯定比您的 using 块长,因此当您尝试访问它并执行抛出异常的行时 excel 已经被释放。

直接解决方案 是不要在这里使用 using。但也许最好在后台工作人员的方法中实例化 excel 变量 ,因为看起来你无论如何都不需要它。

我很确定您的 excel 变量在读取异常时是 Null 变量。不是方法调用中的值。

我怀疑这是由于您所做的后台工作所致。