不同线程访问同一控件导致的不安全错误解决办法

错误原因分析

造成这一错误的原因通常是非创建该控件的线程操作了这个控件,比如主线程创建了窗口A,分线程要关掉窗口A。因为程序并不能确定主线程是不是在操作这个窗口,所以盲目的关闭这个窗口会造成不可预料的错误!(当然,只要你逻辑清楚是不会出错的,但是编译器还是要强制进行安全检查)

解决方案

对于这个问题,最好的解决方案是通过创建该控件的进程操作这个控件,那么怎么在分线程中找到创建该控件的线程呢?答案是使用代理(委托),把分线程不能操作的方法包成代理方法,让分线程中被操作的控件执行这个代理就可以了。

代码实现

场景假设

假设通过FormA去创建FormB,之后在通过新线程去关闭FormB

FormA去创建FormB

private void button1_Click(object sender, EventArgs e)
{
    FormB fb = new FormB();
    fb.ShowDialog();
}

FormA创建新线程管理FormB

private void button1_Click(object sender, EventArgs e)
{
    //其中closeFormMethod为你要管理控件的方法;
    Thread th = new Thread( new ThreadStart(closeFormMethod) );
    th.Start();

    FormB fb = new FormB();
    fb.ShowDialog();
}

分线程中创建代理,并用代理去执行分线程中不能执行的方法

private delegate void HideFrom();
private void closeFormMethod()
{
    //延时3S是为了保证窗口B确确实实被创建了
    Thread.Sleep(3000);
    HideFrom hideFrom = new HideFrom(fb.Close);
    fb.Invoke(hideFrom);
}

解决方案分析

这个代理方法并不是真正由分线程执行的,而是由创建控件的线程执行的,当控件调用invoke方法的时候,会通过控件的控件树找到创建这个控件的父控件,从而找到父控件中创建这个控件的线程,并由这个线程调用代理方法。从而做到线程安全。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值