zoukankan      html  css  js  c++  java
  • 在非UI线程中改变UI控件属性的通用方法

    在.NET中如需在非UI线程中改变UI控件属性时,CLR会抛出异常,提示无法在非UI线程中更新界面上的控件(Cross-thread operation not valid)。一般情况下有两种解决办法。第一种就是设置Control的静态属性CheckForIllegalCrossThreadCalls为False,如下:

    public Form1()
    {
        InitializeComponent();
        Control.CheckForIllegalCrossThreadCalls = false;
    }
    
    private void button1_Click(object sender, EventArgs e)
    {
        Thread thread = new Thread(() =>
        {
            for (int i = 0; i < 100000; i++)
            {
                label1.Text = i.ToString();
                label1.Refresh();
            }
        });
        thread.Start();
    }
    

    另一种办法,就是使用委托,根据控件的InvokeRequired属性判断当前控件的更新操作是否是在另一个线程中。如果是,则使用委托进行方法调用并更新控件。但是这种方法有个缺点,就是需要针对每个控件的属性设置方式创建一些单独的委托和方法,这些委托和方法仅仅是在解决跨线程操作的时候使用。比如,你在另一个线程中需要修改某个label的text时,你就需要创建一个SetLabelText方法,假设你还需要更新TextBox的text,那么你还需要另外创建一个SetTextBoxText方法。

    通过下面的委托和方法的定义,我们实现了“一次定义,多次使用”。请看:

    private delegate void ParameterizedControlUpdate(params object[] args);
    
    private delegate void ControlUpdateDelegate(Component c,
        ParameterizedControlUpdate callback,
        params object[] args);
    
    private void DelegatedControlUpdate(Component c,
        ParameterizedControlUpdate callback,
        params object[] args)
    {
        Control target = (c is Control) ? (c as Control) : this;
        if (target.InvokeRequired)
        {
            ControlUpdateDelegate d = DelegatedControlUpdate;
            target.Invoke(d, new object[] { c, callback, args });
        }
        else
        {
            callback(args);
        }
    }
    

    于是,上面的例子可以改为:

    private void button1_Click(object sender, EventArgs e)
    {
        Thread thread = new Thread(() =>
        {
            for (int i = 0; i < 100000; i++)
            {
                DelegatedControlUpdate(label1, args =>
                    {
                        label1.Text = (string)args[0];
                        label1.Refresh();
                    }, i.ToString());
            }
        });
        thread.Start();
    }
    
  • 相关阅读:
    Atitit.atiJsBridge 新特性v7q329
    atitit.userService 用户系统设计 v6 q413
    atitit.userService 用户系统设计 v6 q413
    Atitit.获取某个服务 网络邻居列表 解决方案
    Hasse神舟笔记本卡logo解决,刷BIOS方法,教你修复神船
    Axure RP 8 注册码
    在本地硬盘安装WinPE系统,实现UEFI引导,摆脱U盘
    cmd实现批量文件的base64加密并双击加密文件后正常运行
    cmd的变量总结
    fiddler几种功能强大的用法
  • 原文地址:https://www.cnblogs.com/daxnet/p/1686950.html
Copyright © 2011-2022 走看看