• 转 在非 UI线程中改变UI控件属性的通用方法 武胜


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

    01public Form1()
    02{
    03    InitializeComponent();
    04    Control.CheckForIllegalCrossThreadCalls = false;
    05}
    06 
    07private void button1_Click(object sender, EventArgs e)
    08{
    09    Thread thread = new Thread(() =>
    10    {
    11        for (int i = 0; i < 100000; i++)
    12        {
    13            label1.Text = i.ToString();
    14            label1.Refresh();
    15        }
    16    });
    17    thread.Start();
    18}

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

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

    01private delegate void ParameterizedControlUpdate(params object[] args);
    02 
    03private delegate void ControlUpdateDelegate(Component c,
    04    ParameterizedControlUpdate callback,
    05    params object[] args);
    06 
    07private void DelegatedControlUpdate(Component c,
    08    ParameterizedControlUpdate callback,
    09    params object[] args)
    10{
    11    Control target = (c is Control) ? (c as Control) : this;
    12    if (target.InvokeRequired)
    13    {
    14        ControlUpdateDelegate d = DelegatedControlUpdate;
    15        target.Invoke(d, new object[] { c, callback, args });
    16    }
    17    else
    18    {
    19        callback(args);
    20    }
    21}

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

    01private void button1_Click(object sender, EventArgs e)
    02{
    03    Thread thread = new Thread(() =>
    04    {
    05        for (int i = 0; i < 100000; i++)
    06        {
    07            DelegatedControlUpdate(label1, args =>
    08                {
    09                    label1.Text = (string)args[0];
    10                    label1.Refresh();
    11                }, i.ToString());
    12        }
    13    });
    14    thread.Start();
    15}
  • 相关阅读:
    [转]在efcore 中创建类 通过实现IEntityTypeConfiguration<T>接口 实现实体类的伙伴类 实现FluentApi
    jboss反序列化漏洞(CVE-2017-12149)
    第一阶段 3、javascript
    vue创建新项目
    vue引入git项目运行测试相关
    javascript基础知识梳理
    关于模式识别作业——利用分类器实现手写数字识别
    Guava 学习
    读书清单
    @JsonInclude(Include.NON_NULL)全局配置
  • 原文地址:https://www.cnblogs.com/zeroone/p/1700231.html
Copyright © 2020-2023  润新知