几何尺寸与公差论坛

 找回密码
 注册
查看: 1827|回复: 0

【转帖】WinForm/Silverlight多线程编程中如何更新UI控件的值

[复制链接]
发表于 2011-7-5 21:06:40 | 显示全部楼层 |阅读模式
http://www.cnblogs.com/yjmyzz/archive/2009/11/25/1610253.html
单线程的winfom程序中,设置一个控件的值是很easy的事情,直接 this.TextBox1.value = "Hello World!";就搞定了,但是如果在一个新线程中这么做,比如:

private void btnSet_Click(object sender, EventArgs e)
{   
    Thread t
= new Thread(new ParameterizedThreadStart(SetTextBoxValue));
   
//当然也可以用匿名委托写成Thread t = new Thread(SetTextBoxValue);
    t.Start("Hello World");
}


void SetTextBoxValue(object obj)
{
   
this.textBox1.Text = obj.ToString();
}

  运行时,会报出一个无情的错误:
线程间操作无效: 从不是创建控件“textBox1”的线程访问它。

究其原因,winform中的UI控件不是线程安全的,如果可以随意在任何线程中改变其值,你创建一个线程,我创建一个线程,大家都来抢着更改"TextBox1"的值,没有任何秩序的话,天下大乱...

解决办法:
1.掩耳盗铃法(Control.CheckForIllegalCrossThreadCalls = false;)--仅Winform有效

using System;
using System.Threading;
using System.Windows.Forms;

namespace ThreadTest
{
   
public partial class Form1 : Form
    {        

        
public Form1()
        {
            InitializeComponent();
            
Control.CheckForIllegalCrossThreadCalls = false;//这一行是关键      
        }
      

        
private void btnSet_Click(object sender, EventArgs e)
        {           
            Thread t
= new Thread(new ParameterizedThreadStart(SetTextBoxValue));
            t.Start(
"Hello World");
        }


        
void SetTextBoxValue(object obj)
        {
            
this.textBox1.Text = obj.ToString();
        }        
    }
}

设置Control.CheckForIllegalCrossThreadCalls为false,相当于不检测线程之间的冲突,允许各路线程随便乱搞,当然最终TextBox1的值到底是啥难以预料,只有天知道,不过这也是最省力的办法

2.利用委托调用--最常见的办法(仅WinForm有效)


using System;
using System.Threading;
using System.Windows.Forms;

namespace ThreadTest
{
   
public partial class Form1 : Form
    {
        
delegate void D(object obj);

        
public Form1()
        {
            InitializeComponent();            
        }
      

        
private void btnSet_Click(object sender, EventArgs e)
        {           
            Thread t
= new Thread(new ParameterizedThreadStart(SetTextBoxValue));
            t.Start(
"Hello World");
        }


        
void SetTextBoxValue(object obj)
        {
            if (textBox1.InvokeRequired)
            {
                D d = new D(DelegateSetValue);
                textBox1.Invoke(d,obj);

            }
            
else
            {
               
this.textBox1.Text = obj.ToString();
            }
        }


        
void DelegateSetValue(object obj)
        {
            
this.textBox1.Text = obj.ToString();
        }
    }
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|Archiver|小黑屋|几何尺寸与公差论坛

GMT+8, 2024-4-27 20:19 , Processed in 0.037505 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表