zoukankan      html  css  js  c++  java
  • 多线程学习笔记之更新UI控件(转载)

    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();
            }
        }
    }

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

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

    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 { setget; }
            
    public object parm { setget; }
        }
    }

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

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

    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());
            }       
        }    
    }
    转自:http://www.cnblogs.com/yjmyzz/archive/2009/11/25/1610253.html
  • 相关阅读:
    16 pymysql模块的使用
    15 可视化工具 Navicat的简单使用
    14 补充 MySQL的创建用户和授权
    13 多表查询
    linux常用查看文件或日志命令
    linux查找大文件命令
    linux测试环境维护之磁盘空间维护
    linux配置IP访问权限
    通过pytty工具代理连接数据库mysql(绕开数据库白名单限制)
    redis安装详解
  • 原文地址:https://www.cnblogs.com/johnwonder/p/1676785.html
Copyright © 2011-2022 走看看