在线程中更新UI
为了更新UI线程,在新线程中用this.Invoke来更新UI上控件的值。
其实这背后是有异常的(有可能会在vs中报出来),因为当你关闭窗体时,this已经不存在了,但访问this.Invoke在新的线程中,新线程本身并没有关掉,这时就会报找不到实例而引发报错。
有可能运行起来并不会发现异常,这是因为主线程关闭后,所有创建的子线程都会关闭的。
解决方案:
方法1:
参考:Timer控件-Forms.Timer\System.Timers.Timer\System.Threading.Timer - hanzq_go - 博客园 (cnblogs.com)
private void FormTimer1_FormClosed(object sender, FormClosedEventArgs e) { System.Environment.Exit(0);//结束进程 }
方法2:
通过一个mark标志,在关闭窗体时,拦截一下,把子线程关闭,然后再把主窗体关闭,这样就没有问题了,自己起的线程,自己要关掉。
using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApp4 { public partial class Form1 : Form { public Form1() { InitializeComponent(); this.Load += Form1_Load; this.FormClosing += Form1_FormClosing; } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (mark) { e.Cancel = true; mark = false; } } static List<Item> list; private void Form1_Load(object sender, EventArgs e) { list = new List<Item> { new Item{ Name="正在上传诊疗项目",Time=8 }, new Item{ Name="正在上传器材",Time=10 }, new Item{ Name="正在上传药品",Time=10 }, new Item{ Name="正在核对",Time=12 } }; } static bool mark; private void button1_Click(object sender, EventArgs e) { mark = true; Task.Run(() => { foreach (var item in list) { if (mark == false) { break; } var dotString = ""; for (var i = 0; i < item.Time; i++) { if (mark == false) { break; } if (i % 6 == 0) { dotString = "."; } else { dotString += "."; } this.Invoke(new Action(() => messageLabel.Text = $"{item.Name}{dotString}")); Thread.Sleep(100); } } //MessageBox.Show("完成医保所有数据同步"); if (mark) { mark = false; MessageBox.Show("完成医保所有数据同步"); } else { this.Invoke(new Action(() => { this.Close(); })); } }); } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?