C# 跨线程访问控件需要注意的问题
C#跨线程访问控件,我们一般 new
一个线程,多线程来操作。今天本以为是这样操作的,可还是卡死程序了。记录一下碰到的这些疑难杂症。
一、怀疑多界面问题
其实,与嵌套多少个控件没关系。
▲ 我是在一个主窗体放了一个panel,然后,在panel里面加载menu1,menu1通过按钮加载menu2;再在么menu2里面new一个线程,跨线程访问textbox。可这样还是被卡死了。
怀疑是在主窗体嵌入的两个menu
,在menu
里面这样操作不行。后面这种情况被我排除了。因为,我把代码复制到主页面,相同功能还是卡死。所以,还是代码有问题。
二、聚焦代码问题
问题其实是,this.textBox1.Invoke(/*调用代码*/)
的调用代码
不能太耗时,与控件本身操作无关的代码。不然就卡死。
开始我是这样写的:
int a = 0;
thread = new Thread(() =>
{
if (this.textBox1.InvokeRequired) {
this.textBox1.Invoke(new Action(() => {
while (true) {
this.textBox1.Text = a++.ToString();
Thread.Sleep(1000);
}
}));
}
});
thread.IsBackground = true;
thread.Start();
把循环放到控件Invoke
外面去
int a = 0;
thread = new Thread(() =>
{
if (this.textBox1.InvokeRequired) {
while (true) {
this.textBox1.Invoke(new Action(() => {
this.textBox1.Text = a++.ToString();
Thread.Sleep(1000);
}));
}
}
});
thread.IsBackground = true;
thread.Start();
上面这样还是不行的,Thread.Sleep(1000);
耗时,且与跨线程访问的控件无关。经测试即使换成耗时的循环for(int i = 0; i < 1000; i++) for(int j = 0; j < 100000; j++);
,这样照样会卡死。
把Thread.Sleep(1000);
放Invoke
外面去
这样能够工作的,不卡。
int a = 0;
thread = new Thread(() =>
{
if (this.textBox1.InvokeRequired) {
while (true) {
this.textBox1.Invoke(new Action(() => {
this.textBox1.Text = a++.ToString();
}));
Thread.Sleep(1000);
}
}
});
thread.IsBackground = true;
thread.Start();
效果如下:
▲ 主页面的textbox计时显示和两层加载的menu中的textbox的计时显示也是没问题的,窗体不冻结卡死。
其实本质上为什么会这样,我是没有明确搞明白的,都是自己去理解,不确定是不是自己理解的这样。也不想花太多的时间去深究了,能实现效果就好。如何学会把时间花在最关键的地方?这是一门学问,越早明白越受益。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了