【问题标题】:'System.AccessViolationException' occurred'System.AccessViolationException' 发生
【发布时间】:2015-07-10 20:10:12
【问题描述】:

更新:添加了发生错误的完整代码块

更新 2:我发现了一个奇怪的异常。当 tabName 变量等于“前一年的服务行”时,代码现在一直在该行上中断。今天早上,为了咧嘴笑,我将选项卡名称更改为“test”,因此 tabName 变量又等于“test”,它的工作频率更高,然后没有。我真的很茫然。

我进行了大量研究,但找不到任何可以解决我的代码中发生的问题的内容。它虽然随机发生。有时它不会发生,有时它会发生在同一个地方,但都发生在这部分代码上(在 templateSheet = templateBook.Sheets[tabName]; 行上):

 public void ExportToExcel(DataSet dataSet, string filePath, int i, int h, Excel.Application excelApp)
    {
            //create the excel definitions again.
            //Excel.Application excelApp = new Excel.Application();
            //excelApp.Visible = true;
            FileInfo excelFileInfo = new FileInfo(filePath);
            Boolean fileOpenTest = IsFileOpen(excelFileInfo);

            Excel.Workbook templateBook;
            Excel.Worksheet templateSheet;

            //check to see if the template is already open, if its not then open it,
            //if it is then bind it to work with it
            if (!fileOpenTest)
            { templateBook = excelApp.Workbooks.Open(filePath); }
            else
            { templateBook = (Excel.Workbook)System.Runtime.InteropServices.Marshal.BindToMoniker(filePath); }


            //this grabs the name of the tab to dump the data into from the "Query Dumps" Tab
                string tabName = lstQueryDumpSheet.Items[i].ToString();

                templateSheet = templateBook.Sheets[tabName];
                excelApp.Calculation = Excel.XlCalculation.xlCalculationManual;

                templateSheet = templateBook.Sheets[tabName];        

            // Copy DataTable
            foreach (System.Data.DataTable dt in dataSet.Tables)
            {
                // Copy the DataTable to an object array
                object[,] rawData = new object[dt.Rows.Count + 1, dt.Columns.Count];

                // Copy the values to the object array
                for (int col = 0; col < dt.Columns.Count; col++)
                {
                    for (int row = 0; row < dt.Rows.Count; row++)
                    { rawData[row, col] = dt.Rows[row].ItemArray[col]; }
                }

                // Calculate the final column letter
                string finalColLetter = string.Empty;
                string colCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                int colCharsetLen = colCharset.Length;

                if (dt.Columns.Count > colCharsetLen)
                { finalColLetter = colCharset.Substring((dt.Columns.Count - 1) / colCharsetLen - 1, 1); }

                finalColLetter += colCharset.Substring((dt.Columns.Count - 1) % colCharsetLen, 1);

                //this grabs the cell address from the "Query Dump" sheet, splits it on the '=' and
                //pulls out only the cell address (i.e., "address=a3" becomes "a3")
                string dumpCellString = lstQueryDumpText.Items[i].ToString();
                string dumpCell = dumpCellString.Split('=').Last();

                //referts to the range in which we are dumping the DataSet.  The upper right hand cell is
                //defined by the 'dumpCell' varaible and the bottom right cell is defined by the 
                //final column letter and the count of rows.
                string firstRef = "";
                string baseRow = "";

                if (char.IsLetter(dumpCell, 1))
                {
                    char[] createCellRef = dumpCell.ToCharArray();
                    firstRef = createCellRef[0].ToString() + createCellRef[1].ToString();
                    for (int z = 2; z < createCellRef.Count(); z++)
                    {
                        baseRow = baseRow + createCellRef[z].ToString();
                    }
                }
                else
                {
                    char[] createCellRef = dumpCell.ToCharArray();
                    firstRef = createCellRef[0].ToString();
                    for (int z = 1; z < createCellRef.Count(); z++)
                    {
                        baseRow = baseRow + createCellRef[z].ToString();
                    }
                }

                int baseRowInt = Convert.ToInt32(baseRow);
                int startingCol = ColumnLetterToColumnIndex(firstRef);
                int endingCol = ColumnLetterToColumnIndex(finalColLetter);

                int finalCol = startingCol + endingCol;
                string endCol = ColumnIndexToColumnLetter(finalCol - 1);
                int endRow = (baseRowInt + (dt.Rows.Count - 1));
                string cellCheck = endCol + endRow;
                string excelRange;

                if (dumpCell.ToUpper() == cellCheck.ToUpper())
                {
                    excelRange = string.Format(dumpCell + ":" + dumpCell);
                }
                else
                {
                    excelRange = string.Format(dumpCell + ":{0}{1}", endCol, endRow);
                }

                //this dumps the cells into the range on Excel as defined above
                templateSheet.get_Range(excelRange, Type.Missing).Value2 = rawData;

                //checks to see if all the SQL queries have been run from the "Query Dump" tab, if not, continue 
                //the loop, if it is the last one, then save the workbook and move on.

                if (i == lstSqlAddress.Items.Count - 1)
                {
                    excelApp.Calculation = Excel.XlCalculation.xlCalculationAutomatic;

                    /*Run through the value save sheet array then grab the address from the corresponding list 
                    place in the address array.  If the address reads "whole sheet" then save the whole page,
                    else set the addresses range and value save that.*/
                    //for (int y = 0; y < lstSaveSheet.Items.Count; y++)
                    //{
                    //    MessageBox.Show("Save Sheet: " + lstSaveSheet.Items[y] + "\n" + "Save Address: " + lstSaveRange.Items[y]);
                    //}

                    //run the macro to hide the unused columns
                    excelApp.Run("ReportMakerExecute");

                    //save excel file as hospital name and move onto the next
                    SaveTemplateAs(templateBook, h);

                    //close the open Excel App before looping back
                    //Marshal.ReleaseComObject(templateSheet);
                    //Marshal.ReleaseComObject(templateBook);
                    //templateSheet = null;
                    //templateBook = null;
                    //GC.Collect();
                    //GC.WaitForPendingFinalizers();
                }
                //Close excel Applications
                //excelApp.Quit();
                //Marshal.ReleaseComObject(templateSheet);
                //Marshal.FinalReleaseComObject(excelApp);
                //excelApp = null;
                //templateSheet = null;
                // GC.Collect();
                //GC.WaitForPendingFinalizers();
            }

    }

try/catch 块也没有用。这是错误:

"An unhandled exception of type 'System.AccessViolationException' occurred inSQUiRE (Sql QUery REtriever) v1.exe.  Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

【问题讨论】:

  • 抱歉,您需要详细说明您的问题。将相关代码和信息整理好,尝试查看内部异常并告诉我们您一直在尝试实现什么...
  • @gustavodidomenico 我已经添加了当/如果发生错误时发生错误的整个块。我在想此时可能是内存缓冲区问题。

标签: c#


【解决方案1】:

System.AccessViolationException 通常会在您尝试访问本机代码(不是 .NET)中未分配的内存时发生。然后 .NET 将其作为此异常转换为托管世界。

您的代码本身没有任何不安全的块。所以我必须在 Excel 中发生访问冲突。

考虑到它有时会发生,有时不会,我会说它可能是由并行 Excel 使用引起的(我认为 Excel COM 不是线程安全的)。

我建议您将所有代码放在 lock 块中,以防止 Excel 开始并行使用。像这样的:

public void ExportToExcel(DataSet dataSet, string filePath, int i, int h, Excel.Application excelApp)
{
    lock(this.GetType()) // You can change here to other instance to me used a mutex
    {
        // Your original code here
    }
}

【讨论】:

  • 谢谢,我试过了,但第一次运行,它抛出了同样的异常。我会牢记并行 excel 继续挖掘。
【解决方案2】:

这么长的故事,三天的测试时间更长,这是因为一个 excel 文件试图打开并填充 SQL 结果。缓冲区被填满并导致异常......它只是在每次运行的同一点发生,因为 excel 文件的加载时间是它工作或失败的决定因素。

所以在加载之后我只是添加了一个延迟执行...同时检查文件是否可访问并停止了故障。 fileOpenTest 取自here

           do
            {
                Task.Delay(2000);
            } 
            while(!fileOpenTest);

【讨论】:

    猜你喜欢
    • 2019-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多