星空网 > 软件开发 > ASP.net

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

线程winfom程序中,设置一个控件的值是很easy的事情,直接 this.TextBox1.value = "Hello World!";就搞定了,但是如果在一个新线程中这么做,比如:

WinForm/Silverlight多线程编程中如何更新UI控件的值
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();
}
WinForm/Silverlight多线程编程中如何更新UI控件的值

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

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

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

WinForm/Silverlight多线程编程中如何更新UI控件的值
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();
        }        
    }
}WinForm/Silverlight多线程编程中如何更新UI控件的值

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

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

WinForm/Silverlight多线程编程中如何更新UI控件的值
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();
        }
    }
}WinForm/Silverlight多线程编程中如何更新UI控件的值

3.利用SynchronizationContext上下文 -- 最神秘的方法(Winform/Silverlight能用)

之所以说它神秘,是因为msdn官方对它的解释据说也是不清不楚 

WinForm/Silverlight多线程编程中如何更新UI控件的值
using System;
using System.Threading;
using System.Windows.Forms;

namespace ThreadTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();            
        }       

        private void btnSet_Click(object sender, EventArgs e)
        {
            Thread t = new Thread(new ParameterizedThreadStart(Run));
            MyPram _p = new MyPram() { context = SynchronizationContext.Current, parm = "Hello World" };
            t.Start(_p);
        }

        void Run(object obj) 
        {
            MyPram p = obj as MyPram;
            p.context.Post(SetTextValue, p.parm);
        }


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


    public class MyPram 
    {
        public SynchronizationContext context { set; get; }
        public object parm { set; get; }
    }
}WinForm/Silverlight多线程编程中如何更新UI控件的值

4.利用BackgroundWorker --最偷懒的办法(Winform/Silverlight通用)

BackgroundWorker会在主线程之外,另开一个后台线程,我们可以把一些处理放在后台线程中处理,完成之后,后台线程会把结果传递给主线程,同时结束自己。

WinForm/Silverlight多线程编程中如何更新UI控件的值
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace ThreadTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();            
        }       

        private void btnSet_Click(object sender, EventArgs e)
        {
            //MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
            using (BackgroundWorker bw = new BackgroundWorker())
            {
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
                bw.DoWork += new DoWorkEventHandler(bw_DoWork);
                bw.RunWorkerAsync("Hello World");
            }
        }

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            //MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
            e.Result = e.Argument;//这里只是简单的把参数当做结果返回,当然您也可以在这里做复杂的处理后,再返回自己想要的结果(这里的操作是在另一个线程上完成的)
        }

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //这时后台线程已经完成,并返回了主线程,所以可以直接使用UI控件了
            this.textBox1.Text = e.Result.ToString();
            //MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
        }       
    }    
}
WinForm/Silverlight多线程编程中如何更新UI控件的值

5.Dispatcher.BeginInvoke--Silverlight的独门秘籍 

WinForm/Silverlight多线程编程中如何更新UI控件的值
WinForm/Silverlight多线程编程中如何更新UI控件的值代码using System.Threading;
using System.Windows.Controls;
using System.Windows.Input;

namespace ThreadTest
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Thread t = new Thread(SetTextValue);
            t.Start("Hello World");
        }

        void SetTextValue(object text) 
        {
            this.Dispatcher.BeginInvoke(() => { this.txt.Text = text.ToString(); });            
        }
    }
}

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

 
转自菩提树下的杨过http://www.cnblogs.com/yjmyzz/archive/2009/11/25/1610253.html



原标题:WinForm/Silverlight多线程编程中如何更新UI控件的值

关键词:winform

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

亚马逊收费巨坑:仅仅填了一个词,佣金从15%变45%!:https://www.ikjzd.com/articles/98098
亚马逊无货源该怎么铺货,ERP可以定制吗?:https://www.ikjzd.com/articles/98099
继双清报税之后,外媒再次曝光中国卖家的逃税丑闻!:https://www.ikjzd.com/articles/9810
如何让亚马逊产品利润爆涨?:https://www.ikjzd.com/articles/98100
新手注意!被吹上天的“亚马逊无货源+店群”模式实际有多坑?:https://www.ikjzd.com/articles/98101
当桌游品牌开始维权,你离冻结还有多远?:https://www.ikjzd.com/articles/98103
长治婚庆女司仪和主持人:https://www.vstour.cn/a/366176.html
北京丰台区水上乐园哪家好玩?:https://www.vstour.cn/a/366177.html
相关文章
我的浏览记录
最新相关资讯
海外公司注册 | 跨境电商服务平台 | 深圳旅行社 | 东南亚物流