C#Invoke委托在多线程中的使用

一步一步跟随着我的脚步看一看

Form上我设置一个button,text属性为“点击开始测试”;现在我想点击它以后,动态变化从1~10赋值

(1)

第一个映入脑中的方式就是这样写

private void button1_Click(object sender, EventArgs e)
{
    button1.Enabled = false;
    for(int i=1;i<10;i++)
    {
        button1.Text = i.ToString();
        Thread.Sleep(1000);
    }
    button1.Text = "点击开始测试";
    button1.Enabled = true;
}

有没有问题?肯定有的啦,我点击以后,界面倒是disable了,但是没有1~10出现,时间一到,恢复enable。为什么呢?

原因:直接主线程休眠是达不到效果的,此时桌面还处于假死状态,更新不了text值。代码放在了UI线程执行,阻塞了UI的显示,所以中间的结果你看不到。实验了两种方式解决:

  1. 在Thread.Sleep(1000);后加 button1.Refresh();
  2. 在Thread.Sleep(1000);后加 Application.DoEvents();

(2)

既然是由于代码放在了UI线程,那我新建个线程,在那里面更新UI控件好了。

private void button1_Click(object sender, EventArgs e)
{
    //启动一个线程
    new Thread(ThreadTask).Start();
}
//线程函数
public void ThreadTask()
{
    button1.Enabled = false;
    for (int i = 0; i < 10; i++)
    {
        button1.Text = i.ToString();
        Thread.Sleep(1000);
    }
    button1.Text = "点击开始测试";
    button1.Enabled = true;
}

出错了!!!

造成这种异常的原因在于,控件是在主线程中创建的(比如this.Controls.Add(...);),进入控件的事件响应函数时,是在控件所在的线程,并不是主线程。在控件的事件响应函数中改变控件的状态,可能与主线程发生线程冲突。如果主线程正在重绘控件外观,此时在别的线程改变控件外观,就会造成画面混乱。

(3)

下面该主角出场了,C#的委托机制,由于历史的原因,有这么几种形式:

//第一种
button1.Invoke(new EventHandler(delegate{button1.Text = "关闭";}));
//第二种
this.Invoke(new EventHandler(delegate{button1.Text = "关闭";}));
//第三种 网上说自C# 3.0开始就有了
this.Invoke(new Action(() =>{ button1.Text = "关闭";}));

我喜欢用第三种,好记,哈哈。好了,接下来实现以下吧!

private void button1_Click(object sender, EventArgs e)
{         
    //启动一个线程
    new Thread(ThreadTask).Start();
}
        //线程函数
public void ThreadTask()
{
    //首先将button对象禁用
    this.Invoke(new Action(() =>
    {
        button1.Enabled = false;
    }));
    for (int i = 0; i < 10; i++)
    {
        this.Invoke(new Action(() =>
        {
            button1.Text = i.ToString();
        }));
        Thread.Sleep(1000);
    }
    //虽然不是循环内,请不要忘记,你的调用依然在辅助线程中,所以,还是需要invoke的。
    //还原状态,设置按钮的文本为初始状态,设置按钮可用。
    this.Invoke(new Action(() =>
    {
        button1.Text = "点击开始测试";
        button1.Enabled = true;
    }));

    

}

大功告成喽!!

 

  • 12
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值