You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止MainForm处理时关闭?e.Cancel不生效问题排查

问题分析与解决方案

核心问题

  1. 错误的主窗口实例:在Books.cs的btnClick方法中,你新建了一个MainForm实例MainForm mainform = new MainForm();,但这个实例并非当前正在显示的主窗口。调用SetProcessingState修改的是这个新实例的isProcessing字段,而非实际运行的主窗口状态,导致主窗口FormClosing事件中isProcessing始终为false,无法触发关闭阻止逻辑。同时这个新实例从未显示,它的FormClosing事件自然不会触发。
  2. 事件绑定可能缺失:如果主窗口的FormClosing事件未在设计器或代码中正确绑定到MainForm_FormClosing方法,断点也不会触发。

修复步骤

1. 传递当前主窗口实例给Books.cs

修改Books.cs的btnClick方法,接收当前运行的MainForm实例,而非新建:

// Books.cs
private async Task btnClick(MainForm mainForm) // 接收外部传入的主窗口实例
{
    // 移除新建MainForm的代码:MainForm mainform = new MainForm();
    try
    {
        mainForm.SetProcessingState(true);

        cts = new CancellationTokenSource();

        PleaseWait pleasewait = new PleaseWait();
        pleasewait.Closed += PleaseWait_Closed;
 
        pleasewait.Show();

        try
        {
            // 通过主窗口实例获取Excel路径
            string path = mainForm.TxtBox.Text;
            await Task.Run(() => ProcessBookstoreExcel(cts.Token, path));
        }
        catch(OperationCanceledException)
        {
            cancel = true;
            pleasewait.Close();
            // MessageBox.Show("操作已取消");
        }
        catch(Exception ex)
        {
            pleasewait.Close();
            MessageBox.Show(ex.Message);
        }
        pleasewait.Closed -= PleaseWait_Closed;
        pleasewait.Close();

        if(!cancel)
            MessageBox.Show("处理完成!");
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        cts?.Dispose();
        cts = null;
        mainForm.SetProcessingState(false);
    }
}

// 修改ProcessBookstoreExcel方法,接收路径参数
private void ProcessBookstoreExcel(CancellationToken cancellationToken, string path)
{
    try
    {
        ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
        var records = new List<BookRecord>();

        using (var package = new ExcelPackage(new FileInfo(path)))
        {
            ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
            int rowCount = worksheet.Dimension.Rows;

            for (int row = 2; row <= rowCount; row++)
            {
                cancellationToken.ThrowIfCancellationRequested();

                records.Add(new BookRecord
                {
                    LineNumber = row,
                    ISBN = worksheet.Cells[row, 1].Text,
                    Title = worksheet.Cells[row, 2].Text,
                    Stock = int.Parse(worksheet.Cells[row, 3].Text),
                    Price = decimal.Parse(worksheet.Cells[row, 4].Text),
                    PublisherID = int.Parse(worksheet.Cells[row, 5].Text),
                    PublisherName = worksheet.Cells[row, 6].Text
                });
            }
        }

        var discrepancies = new List<Discrepancy>();
        var groupedRecords = new Dictionary<string, Dictionary<string, (decimal Price, int Stock)>>();

        foreach (var record in records)
        {
            cancellationToken.ThrowIfCancellationRequested();
 
            var publisherKey = record.PublisherID.ToString();
            var isbnKey = record.ISBN;

            if (!groupedRecords.ContainsKey(publisherKey))
            {
                groupedRecords[publisherKey] = new Dictionary<string, (decimal Price, int Stock)>();
            }

            if (!groupedRecords[publisherKey].ContainsKey(isbnKey))
            {
                groupedRecords[publisherKey][isbnKey] = (record.Price, record.Stock);
            }
            else
            {
                var existing = groupedRecords[publisherKey][isbnKey];
                if (existing.Price != record.Price || existing.Stock != record.Stock)
                {
                    discrepancies.Add(new Discrepancy
                    {
                        LineNumber = record.LineNumber,
                        Publisher = record.PublisherName,
                        Title = record.Title
                    });
                }
            }
        }

        WriteDiscrepancies(discrepancies);
    }
    catch(OperationCanceledException)
    {
        throw;
    }
    catch(Exception ex)
    {
        throw;
    }
}

2. 在MainForm中正确调用btnClick

在MainForm的Submit按钮点击事件中,传递当前实例给Books的btnClick方法:

// MainForm.cs
private async void btnSubmit_Click(object sender, EventArgs e)
{
    Books booksHandler = new Books();
    await booksHandler.btnClick(this); // 传递当前主窗口实例
}

3. 确保FormClosing事件正确绑定

检查MainForm的构造函数,确保FormClosing事件已绑定:

// MainForm.cs构造函数
public MainForm()
{
    InitializeComponent();
    this.FormClosing += MainForm_FormClosing; // 手动绑定事件(如果设计器未绑定)
}

4. 优化FormClosing提示逻辑(可选)

添加提示告知用户无法关闭的原因:

// MainForm.cs
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
    if (isProcessing)
    {
        e.Cancel = true;
        MessageBox.Show("当前正在处理任务,无法关闭窗口!");
    }
}

额外注意事项

  • 确保TxtBox控件可被访问:可以将MainForm中TxtBox的Modifiers属性设为Public,或添加公开属性获取路径:
    // MainForm.cs
    public string ExcelPath => TxtBox.Text;
    
    之后在Books.cs中使用mainForm.ExcelPath获取路径。

内容的提问来源于stack exchange,提问作者Anonymous

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:24:54