跨线程访问控件的问题

fwc 2014-10-23 03:26:23
我申请了一个定时器,定期调用主界面的一个函数更新显示。为了防止跨线程冲突,所有采用如下方式

if(this.InvokeRequired == true)
{
//do invoke method
}
else
;//do normal method


但是通过断点,发现定时器过来的调用,第一次required是false,后面都是true.

定时器是在主窗体的构造函数中创建的,由于创建过程较长,因此主界面会延迟一会出现,猜测是否第一次定时事件时,主界面控件创建了,但没有绑定,因此此时跨线程调用是安全的。后几次定时器事件,主界面控件绑定完成,此时跨线程访问就不是安全的了,因此提示变为true。

不知道是否如此理解,希望给予指教。
...全文
232 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
fwc 2014-11-04
  • 打赏
  • 举报
回复
感谢各位。 定时器里是定时到服务器获取数据,并根据数据刷新主界面上的一个显示,比如股票报价吧。 确实第一次调用,显示控件创建了,但是并没有和主界面绑定,因此更新是没有关系的。 之后绑定了,也就分处不同线程了,自然就需要考虑跨线程了。 我用的是System.Timers.Timer,自己代码里创建的。 #3 我就是把自己代码删除了具体逻辑,好说明些,当然原始代码也是网上抄的....
threenewbee 2014-10-24
  • 打赏
  • 举报
回复
除了界面更新的代码以外,其它不要放在invoke的委托里面。
  • 打赏
  • 举报
回复
不知道你如何“创建”的,也就不可能知道“第一次调用”这个方法是如何发生的。 实际上先不用纠结这个问题。只要是这个方法有可能在子线程中被调用,同时又有可能在主线程中被调用,那么你就这样写代码就行了,只要它通过测试就好了。比如说你为“脚下的地盘”画了几个步骤的格子,你就不需要因为担心格子以外的东西而迈不开步。 另外正如#6楼所说,你在子线程中去这样调用“主界面的一个函数”,这可能是一个设计上的错误。一个方法应该至少分为两部分执行,一部分是可以在子线程执行的,另一部是最终的显示。只有后面的部分需要注册给主线程去执行。如果两部分全都注册给主线程执行,那么你使用线程就是多余的,反而让你的程序变慢,没有意义了。
xian_wwq 2014-10-24
  • 打赏
  • 举报
回复
5楼给的例子很完整了 timer因为可重入,所以下断点调试timer 不是个好的选择 打印日志信息要靠谱的多
江南小鱼 2014-10-24
  • 打赏
  • 举报
回复
timer间隔设置1分钟,再调代码。
QQ234788028 2014-10-23
  • 打赏
  • 举报
回复

        private delegate void lblcountInvoke(string txt);
        private void SetlblcountText(string txt)
        {
            if (lblcount.InvokeRequired)
            {
                lblcountInvoke _myInvoke = new lblcountInvoke(SetlblcountText);
                this.Invoke(_myInvoke, new object[] { txt });
            }
            else
            {
                lblcount.Text = txt;
            }
        }
卧_槽 2014-10-23
  • 打赏
  • 举报
回复
瞎折腾。
於黾 2014-10-23
  • 打赏
  • 举报
回复
还有, 你是否抄的网上的代码,把 if(this.InvokeRequired == true) { //do invoke method } else ;//do normal method 这两个过程合一了 就是使用了个递归,如果判断需要跨线程,然后invork还是执行的这个函数
exception92 2014-10-23
  • 打赏
  • 举报
回复
应该是第一次 timer 没有启动,等过了延迟,timer启动了 就成跨线程调用了。
於黾 2014-10-23
  • 打赏
  • 举报
回复
定时器有3种,你使用的是哪一种? 如果是system.forms.form.timer(就是跟你从工具箱里拖出来的一样),不需要跨线程,直接可以操作form控件 如果是thread.timer,是线程,需要使用invork 还有,你在timer里断点,是没有意义的 代码停了,timer不会停 也就是说,你只是此次执行过程停在断点了,timer会继续触发下一次的调用 你需要把timer时间设置的足够长,比如30秒,然后再断点看

110,571

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧