.NET7 Winform关闭时异步MySQL任务异常的解决方法
.NET7 WinForms异步查询子窗体关闭空引用问题解决
核心问题
子窗体关闭后,后台异步MySQL查询仍在运行,完成后尝试绑定已被销毁的图表控件,触发System.NullReferenceException。
正确处理方案
1. 子窗体侧管理取消令牌
在子窗体中创建CancellationTokenSource,关闭时取消令牌,终止后台任务:
public partial class ChildForm : Form { private CancellationTokenSource _cts; public ChildForm() { InitializeComponent(); _cts = new CancellationTokenSource(); _ = LoadStatsAsync(_cts.Token); } private async Task LoadStatsAsync(CancellationToken token) { try { var stats = await Queries.GetStatisticsAsync(token); // 绑定前检查窗体未释放且任务未取消 if (!IsDisposed && !token.IsCancellationRequested) { chart1.DataSource = stats; // 完成图表绑定的后续逻辑 } } catch (OperationCanceledException) { // 任务被取消,无需处理 } catch (Exception ex) { MessageBox.Show($"统计数据加载失败:{ex.Message}"); } } protected override void OnFormClosed(FormClosedEventArgs e) { base.OnFormClosed(e); _cts.Cancel(); _cts.Dispose(); } }
2. Queries类中集成取消令牌
将令牌传递到MySQL异步操作的每一步,确保查询能被及时终止,避免无效资源占用:
public static class Queries { public static async Task<List<StatModel>> GetStatisticsAsync(CancellationToken token) { var statsList = new List<StatModel>(); var connString = "你的MySQL连接字符串"; using var conn = new MySqlConnection(connString); await conn.OpenAsync(token); var query = "SELECT record_date, stat_value FROM statistics_table"; using var cmd = new MySqlCommand(query, conn); using var reader = await cmd.ExecuteReaderAsync(token); while (await reader.ReadAsync(token)) { statsList.Add(new StatModel { RecordDate = reader.GetDateTime(0), StatValue = reader.GetInt32(1) }); } return statsList; } }
3. 绑定前的双重防护
即使任务没被取消,也可能存在窗体已释放的情况,必须在绑定图表前做检查,避免空引用:
if (!this.IsDisposed && !token.IsCancellationRequested) { // 执行图表绑定操作 }
关键注意点
- 窗体关闭时必须调用
_cts.Cancel()和_cts.Dispose(),防止资源泄漏。 - 所有MySQL异步方法都要传入取消令牌,才能真正终止正在执行的查询,而不是只在代码层面判断。
OperationCanceledException是任务被取消的正常结果,不需要弹出错误提示。
内容的提问来源于stack exchange,提问作者Ivaylo
相关产品推荐
相关产品推荐

