如何阻止MainForm处理时关闭?e.Cancel不生效问题排查
问题分析与解决方案
核心问题
- 错误的主窗口实例:在
Books.cs的btnClick方法中,你新建了一个MainForm实例MainForm mainform = new MainForm();,但这个实例并非当前正在显示的主窗口。调用SetProcessingState修改的是这个新实例的isProcessing字段,而非实际运行的主窗口状态,导致主窗口FormClosing事件中isProcessing始终为false,无法触发关闭阻止逻辑。同时这个新实例从未显示,它的FormClosing事件自然不会触发。 - 事件绑定可能缺失:如果主窗口的
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,或添加公开属性获取路径:
之后在Books.cs中使用// MainForm.cs public string ExcelPath => TxtBox.Text;mainForm.ExcelPath获取路径。
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

