C# WinForm - 关闭主窗体时 EXE 不会终止

标签 c# winforms process oledb

我正在开发一个 WinForms 应用程序,它广泛使用 OleDB(以及 NPOI)来读取和写入 Excel 工作簿。我将在前面说,如果我只是启动应用程序并立即关闭它,应用程序和 EXE 就会正常终止。用户可以执行的第一个操作是单击按钮打开 XLSX 文件。然后,我在内存中初始化一个数据表并使用以下代码来填充它:

打开连接:

public static OleDbConnection GetConnection(string filePath)
    {
        var url = @"Provider=Microsoft.ACE.OLEDB.12.0;" +
            "Data Source=" + filePath + ";" +
            "Extended Properties='Excel 12.0 Xml; HDR=YES; IMEX=1;';";

        try
        {
            var con = new OleDbConnection(url);

            con.Open();

            return con;
        }
        catch (Exception e)
        {
            throw new ArgumentException($"Unable to open connection to workbook with url \"{url}\"", e);
        }
    }

填写数据表:

public static void PopulateDataTable(string filePath, DataTable dt)
    {
        using var con = GetConnection(filePath);

        using var sda = new OleDbDataAdapter(new OleDbCommand("Select * From [" + GetSheetName(con) + "]", con));
        sda.Fill(dt);
        sda.Dispose();

        con.Close();
        con.Dispose();
    }

第一个方法仅用于验证文件的 header ,并且由调用代码显式关闭和处置。它也在 using block 中,我确实意识到那里有一些冗余,但我很绝望。

一旦根据预先确定的列标题列表证明文件有效,就会调用第二种方法。一旦执行此操作,关闭主窗体似乎会关闭应用程序,但任务管理器中仍然存在一个带有单个线程的延迟进程。

我尝试将 Application.Exit()Environment.Exit(0) 添加到 FormClosing 方法中,该方法确实会终止进程,但不会在显示沙漏和日志记录之前事件查看器中出现以下错误:

Faulting application name: SomeApp.exe, version: 1.0.0.0, time stamp: 0x62cf0b31
Faulting module name: mso20win32client.dll, version: 0.0.0.0, time stamp: 0x62df2f51
Exception code: 0xc000041d
Fault offset: 0x000185ed
Faulting process id: 0x27f24
Faulting application start time: 0x01d8bc7d9dd155ac
Faulting application path: C:\Dev\VisualStudioProjects\SomeApp\Final\SomeApp.exe
Faulting module path: C:\Program Files (x86)\Common Files\Microsoft Shared\Office16\mso20win32client.dll
Report Id: 4a58bd92-6541-4def-a04d-01ed0668d38b
Faulting package full name: 
Faulting package-relative application ID: 

还记录了第二个事件,除了异常代码 0xc0000005 之外,该事件完全相同。我怀疑这个问题也是导致 Windows Defender 误报检测的原因。我无法弄清楚这个挥之不去的线程是什么以及如何让代码正确地杀死它。

最佳答案

我通过实现一个纯粹基于 NPOI 的读取解决方案而不使用 OleDB 解决了这个问题(很好的摆脱):

public static void PopulateDatatableNPOI(string filePath, DataTable dt, bool createHeaders)
    {
        using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);

        var sheet = new XSSFWorkbook(stream).GetSheetAt(0);

        if (createHeaders)
        {
            var headerRow = sheet.GetRow(0);
            foreach (var headerCell in headerRow)
                dt.Columns.Add(headerCell.ToString());
        }

        for (int i = 1; i < sheet.PhysicalNumberOfRows; i++)
        {
            var sheetRow = sheet.GetRow(i);
            var dtRow = dt.NewRow();
            dtRow.ItemArray = dt.Columns
                .Cast<DataColumn>()
                .Select(c => sheetRow.GetCell(c.Ordinal, MissingCellPolicy.CREATE_NULL_AS_BLANK).ToString())
                .ToArray();
            dt.Rows.Add(dtRow);
        }
    }

EXE 现在可以正确终止!

关于C# WinForm - 关闭主窗体时 EXE 不会终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73544867/

相关文章:

c# - 当锁定持续时间尚未过去时,Azure 服务总线对非分区队列抛出 MessageLockLostException

c# - 创建下载加速器

c# - C#中如何使用更多的DOS命令

c# - 关于win应用程序c#中的缓存数据

c# - 如何创建一个在超时后重新发送 HTTP 请求的 Observable 序列?

c# - 在 ZedGraph 中显示 Y 轴线

c# - 如何整齐地对齐文本框中的文本并在导出到 .txt 时保留它

c++ - 为什么QProcess::readAllStandardOutput不读取所有输出 channel ?

c - 如何让 tcsetpgrp() 在 C 中工作?

c# - 检测操作系统版本 - Windows Phone 7 或 Windows Phone 8?