简体   繁体   中英

Program doesn't close when I hit the X button top right (Visual Studio, Forms, C#)

It just doesn't react at all if I hit the X button. Not even alt+f4 works

at first I read in two excel files, the read out data is used for some calculation. Edit: Could be that it is an interOp problem:

 System.Data.DataTable dt = new System.Data.DataTable();
            try
            {
                xlApp = new Excel.Application();
                Workbook workbook = xlApp.Workbooks.Open(filePath);
                xlBook = workbook;
                dynamic xlSheet = xlBook.Worksheets[sheetName];
                dynamic xlRange = xlSheet.UsedRange;
                DataRow row = null;
                for (int i = 1; i <= xlRange.Rows.Count; i++)
                {
                    if (i != 1)
                        row = dt.NewRow();
                    for (int j = 1; j <= xlRange.Columns.Count; j++)
                    {
                        if (i == 1)
                            dt.Columns.Add(xlRange.Cells[1, j].value);
                        else
                            row[j - 1] = xlRange.Cells[i, j].value;
                    }
                    if (row != null)
                        dt.Rows.Add(row);
                }
                xlApp = null;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                xlBook.Close();
                //xlApp.Quit();
                if (xlApp != null)
                {
                    xlApp.Quit();
                    xlApp = null;


                }

            }

Everytime you hit the add button on the form starts the calculation and adds a row to a grid view.

Edit: I triggered an event to close the app, but it still doesnt work:

private const int WM_CLOSE = 0x0010;
protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_CLOSE)
    {
        var autoValidate = this.AutoValidate;
        this.AutoValidate = AutoValidate.Disable;
        base.WndProc(ref m);
        this.AutoValidate = autoValidate;
    }
    else
        base.WndProc(ref m);
}
     protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);

            if (e.CloseReason == CloseReason.WindowsShutDown) return;

            // Confirm user wants to close
            switch (MessageBox.Show(this, "Are you sure you want to close?", "Closing", MessageBoxButtons.YesNo))
            {
                case DialogResult.No:
                    e.Cancel = true;

                    break;
                default:
                    break;
            }
        }

Your application is stuck in a tight loop iterating over all the content of the Excel file and isn't releasing control back to the UI thread so that it can handle events.

At the bottom of your outermost for loop, call Application.DoEvents() to allow the UI to update and respond to form and control events.

Based on your last comment that it might indeed be an interop problem, I wanted to post a minimal example of using the Microsoft.Office.Interop.Excel in a way that disposes of it properly. Because this sample intentionally leaves out the System.DataTable aspects of your code, hopefully it will help you isolate the issue.


Initialize the _xlApp member variable

    public MainForm()
    {
        InitializeComponent();
        _xlApp = new Microsoft.Office.Interop.Excel.Application();            
    }
    private readonly Application _xlApp;
    private Workbook _xlBook = null;

Use the Dispose method (this is probably located in the MainForm.Designer.cs file) to quit the Excel app instance.

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (components != null)
            {
                components.Dispose();
            }
            _xlBook?.Close();
            _xlApp.Quit();
        }
        base.Dispose(disposing);
    }

Use the Excel Visible checkbox to Show/Hide the app

    private void checkBoxExcelVisible_CheckedChanged(object sender, EventArgs e)
    {
        Cursor = Cursors.WaitCursor;
        BeginInvoke((MethodInvoker)delegate 
        {
            _xlApp.Visible = checkBoxExcelVisible.Checked; 
            checkBoxWorkbookOpen.Visible = _xlApp.Visible;
            Cursor = Cursors.Default;
        });
    }

显示excel


Use the Workbook Open checkbox to interact with the the workbook cells and copy them to the textbox.

    private void checkBoxWorkbookOpen_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBoxWorkbookOpen.Checked)
        {
            var filePath = System.IO.Path.Combine(
                AppDomain.CurrentDomain.BaseDirectory,
                "Excel",
                "TestCells.xlsx");

            _xlBook = _xlApp.Workbooks.Open(filePath);
            Worksheet xlSheet = _xlBook.Sheets["Sheet1"];
            Range xlRange = xlSheet.Range["A1", "B4"];

            textBox1.Clear();
            for (int i = 1; i <= xlRange.Rows.Count; i++)
            {
                var line = new List<string>();
                for (int j = 1; j <= xlRange.Columns.Count; j++)
                {
                    Range range = xlRange.Cells[i, j];
                    line.Add(range.Value2);
                }
                textBox1.AppendText(string.Join(" | ", line));
                textBox1.AppendText(Environment.NewLine);
            }
        }
        else
        {
            _xlBook?.Close();
            _xlBook = null;
        }
    }
}

与工作簿交互

When I test this, everything disposes correctly under a variety of test conditions. See if you can repro.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM