zoukankan      html  css  js  c++  java
  • C#后台线程和UI的交互

    http://www.cnblogs.com/Wizardh/articles/963097.html

    在C#中,从Main()方法开始一个默认的线程,一般称之为主线程,如果在这个进行一些非常耗CPU的计算,那么UI界面就会被挂起而处于假死状态,也就是说无法和用户进行交互了,特别是要用类似进度条来实时显示一些提示信息的时候,这种情况就显得很糟糕。如果多开一些线程来完成一些耗时的计算,那么工作线程也是无法如此更新UI界面中的元素的,比如直接显示一个提示信息:label1.Text=outstring,原因很简单UI属于默认的主线程,而线程间是不能这样直接访问彼此的成员的。
      如果要解决以上的两个问题,那么可以借助C#中的Delegate和控件类中的Invoke()方法来搞定。
      这里给出的例子比较简单,主要思路是:在Main()中启动其它的线程作为后台进程,其中一个线程是实时显示当前的时间,一个线程是显示一些随机数,这样一来三个线程同时运行,彼此通过代理来联系。
      

    Code
    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using System.Threading;

    namespace MutliThreadedWinFormsApp
    {
        
    public class Form1 : System.Windows.Forms.Form
        
    {
            
    private Thread currentTimeThread = null;
            
    private Thread randomNumbersThread = null;
            
    private System.Windows.Forms.Label label1;
            
    private System.Windows.Forms.TextBox currentTime;
            
    private System.Windows.Forms.Label label2;
            
    private System.Windows.Forms.TextBox randomNumbers;
            
    private System.Windows.Forms.GroupBox threadManager;
            
    private System.Windows.Forms.Button pause;
            
    private System.Windows.Forms.Button stop;
            
    private System.Windows.Forms.Button start;
            
    private System.Windows.Forms.RadioButton manageTime;
            
    private System.Windows.Forms.RadioButton manageNumbers;
            
    private System.Windows.Forms.RadioButton manageBoth;
            
    private System.ComponentModel.Container components = null;

            
    public Form1()
            
    {
                InitializeComponent();
                
                
    //创建新的工作线程
                currentTimeThread = new Thread(new ThreadStart(CountTime));
                currentTimeThread.IsBackground 
    = true;
                
                randomNumbersThread 
    = new Thread(new ThreadStart(GenerateRandomNumbers));
                randomNumbersThread.IsBackground 
    = true;
            }


            
    protected override void Dispose( bool disposing )
            
    {
                
    if( disposing )
                
    {
                    
    if (components != null
                    
    {
                        components.Dispose();
                    }

                }

                
    base.Dispose( disposing );
            }


            
    UI设计#region UI设计
            
    private void InitializeComponent()
            
    {
                
    this.label1 = new System.Windows.Forms.Label();
                
    this.currentTime = new System.Windows.Forms.TextBox();
                
    this.label2 = new System.Windows.Forms.Label();
                
    this.randomNumbers = new System.Windows.Forms.TextBox();
                
    this.threadManager = new System.Windows.Forms.GroupBox();
                
    this.manageBoth = new System.Windows.Forms.RadioButton();
                
    this.manageNumbers = new System.Windows.Forms.RadioButton();
                
    this.manageTime = new System.Windows.Forms.RadioButton();
                
    this.pause = new System.Windows.Forms.Button();
                
    this.stop = new System.Windows.Forms.Button();
                
    this.start = new System.Windows.Forms.Button();
                
    this.threadManager.SuspendLayout();
                
    this.SuspendLayout();
                
    // 
                
    // label1
                
    // 
                this.label1.AutoSize = true;
                
    this.label1.Location = new System.Drawing.Point(824);
                
    this.label1.Name = "label1";
                
    this.label1.Size = new System.Drawing.Size(7913);
                
    this.label1.TabIndex = 0;
                
    this.label1.Text = "现在的时间:";
                
    // 
                
    // currentTime
                
    // 
                this.currentTime.Location = new System.Drawing.Point(8823);
                
    this.currentTime.Name = "currentTime";
                
    this.currentTime.ReadOnly = true;
                
    this.currentTime.Size = new System.Drawing.Size(15720);
                
    this.currentTime.TabIndex = 1;
                
    // 
                
    // label2
                
    // 
                this.label2.AutoSize = true;
                
    this.label2.Location = new System.Drawing.Point(1456);
                
    this.label2.Name = "label2";
                
    this.label2.Size = new System.Drawing.Size(4313);
                
    this.label2.TabIndex = 2;
                
    this.label2.Text = "随机数";
                
    // 
                
    // randomNumbers
                
    // 
                this.randomNumbers.Location = new System.Drawing.Point(1672);
                
    this.randomNumbers.Name = "randomNumbers";
                
    this.randomNumbers.ReadOnly = true;
                
    this.randomNumbers.Size = new System.Drawing.Size(22920);
                
    this.randomNumbers.TabIndex = 3;
                
    // 
                
    // threadManager
                
    // 
                this.threadManager.Controls.Add(this.manageBoth);
                
    this.threadManager.Controls.Add(this.manageNumbers);
                
    this.threadManager.Controls.Add(this.manageTime);
                
    this.threadManager.Controls.Add(this.pause);
                
    this.threadManager.Controls.Add(this.stop);
                
    this.threadManager.Controls.Add(this.start);
                
    this.threadManager.Location = new System.Drawing.Point(16104);
                
    this.threadManager.Name = "threadManager";
                
    this.threadManager.Size = new System.Drawing.Size(229154);
                
    this.threadManager.TabIndex = 7;
                
    this.threadManager.TabStop = false;
                
    this.threadManager.Text = "工作线程控制";
                
    // 
                
    // manageBoth
                
    // 
                this.manageBoth.Location = new System.Drawing.Point(3474);
                
    this.manageBoth.Name = "manageBoth";
                
    this.manageBoth.Size = new System.Drawing.Size(10416);
                
    this.manageBoth.TabIndex = 12;
                
    this.manageBoth.Text = "同时运行";
                
    this.manageBoth.CheckedChanged += new System.EventHandler(this.manageBoth_CheckedChanged);
                
    // 
                
    // manageNumbers
                
    // 
                this.manageNumbers.Location = new System.Drawing.Point(3450);
                
    this.manageNumbers.Name = "manageNumbers";
                
    this.manageNumbers.Size = new System.Drawing.Size(10416);
                
    this.manageNumbers.TabIndex = 11;
                
    this.manageNumbers.Text = "更新随机数线程";
                
    this.manageNumbers.CheckedChanged += new System.EventHandler(this.manageNumbers_CheckedChanged);
                
    // 
                
    // manageTime
                
    // 
                this.manageTime.Location = new System.Drawing.Point(3426);
                
    this.manageTime.Name = "manageTime";
                
    this.manageTime.Size = new System.Drawing.Size(10416);
                
    this.manageTime.TabIndex = 10;
                
    this.manageTime.Text = "更新时间线程";
                
    this.manageTime.CheckedChanged += new System.EventHandler(this.manageTime_CheckedChanged);
                
    // 
                
    // pause
                
    // 
                this.pause.Location = new System.Drawing.Point(84115);
                
    this.pause.Name = "pause";
                
    this.pause.Size = new System.Drawing.Size(5423);
                
    this.pause.TabIndex = 9;
                
    this.pause.Text = "暂停";
                
    this.pause.Click += new System.EventHandler(this.pause_Click);
                
    // 
                
    // stop
                
    // 
                this.stop.Location = new System.Drawing.Point(158115);
                
    this.stop.Name = "stop";
                
    this.stop.Size = new System.Drawing.Size(5123);
                
    this.stop.TabIndex = 8;
                
    this.stop.Text = "停止";
                
    this.stop.Click += new System.EventHandler(this.stop_Click);
                
    // 
                
    // start
                
    // 
                this.start.Location = new System.Drawing.Point(6115);
                
    this.start.Name = "start";
                
    this.start.Size = new System.Drawing.Size(5023);
                
    this.start.TabIndex = 7;
                
    this.start.Text = "开始";
                
    this.start.Click += new System.EventHandler(this.start_Click);
                
    // 
                
    // Form1
                
    // 
                this.AutoScaleBaseSize = new System.Drawing.Size(513);
                
    this.ClientSize = new System.Drawing.Size(253271);
                
    this.Controls.Add(this.threadManager);
                
    this.Controls.Add(this.randomNumbers);
                
    this.Controls.Add(this.label2);
                
    this.Controls.Add(this.currentTime);
                
    this.Controls.Add(this.label1);
                
    this.Name = "Form1";
                
    this.Text = "工作线程和UI的交互";
                
    this.Closing += new System.ComponentModel.CancelEventHandler(this.Form1_Closing);
                
    this.threadManager.ResumeLayout(false);
                
    this.ResumeLayout(false);
                
    this.PerformLayout();
            }

            
    #endregion


            
            [STAThread]
            
    static void Main() 
            
    {
                Application.Run(
    new Form1());
            }


            
    private void start_Click(object sender, System.EventArgs e)
            
    {
                
    bool bTime = false, bRandomNumbers = false;

                
    if( manageTime.Checked || manageBoth.Checked )
                    bTime 
    = true;
                
    if( manageNumbers.Checked || manageBoth.Checked )
                    bRandomNumbers 
    = true;

                
    if( bTime )
                    currentTimeThread.Start();
                
                
    if( bRandomNumbers )
                    randomNumbersThread.Start();

                start.Enabled 
    = false;
                stop.Enabled 
    = true;
                pause.Enabled 
    = true;
            }


            
    private void stop_Click(object sender, System.EventArgs e)
            
    {
                
    bool bTime = false, bRandomNumbers = false;

                
    if( manageTime.Checked == true || manageBoth.Checked == true )
                    bTime 
    = true;
                
    if( manageNumbers.Checked == true || manageBoth.Checked == true )
                    bRandomNumbers 
    = true;

                
    if( bTime )
                
    {
                    currentTimeThread.Abort();
                    currentTimeThread.Join();

                    currentTimeThread 
    = new Thread(new ThreadStart(CountTime));
                    currentTimeThread.IsBackground 
    = true;
                }


                
    if( bRandomNumbers )
                
    {
                    randomNumbersThread.Abort();
                    randomNumbersThread.Join();

                    randomNumbersThread 
    = new Thread(new ThreadStart(GenerateRandomNumbers));
                    randomNumbersThread.IsBackground 
    = true;
                }


                start.Enabled 
    = true;
                stop.Enabled 
    = false;
                pause.Enabled 
    = false;
            }


            
    private void pause_Click(object sender, System.EventArgs e)
            
    {
                
    bool bTime = false, bRandomNumbers = false;

                
    if( manageTime.Checked == true || manageBoth.Checked == true )
                    bTime 
    = true;
                
    if( manageNumbers.Checked == true || manageBoth.Checked == true )
                    bRandomNumbers 
    = true;

                
    if( bTime )
                
    {
                    
    if0 != (currentTimeThread.ThreadState & ( ThreadState.Suspended | ThreadState.SuspendRequested ) ) )
                        currentTimeThread.Resume();
                    
    else
                        currentTimeThread.Suspend();
                }



                
    if( bRandomNumbers )
                
    {
                    
    if0 != (randomNumbersThread.ThreadState & ( ThreadState.Suspended | ThreadState.SuspendRequested ) ) )
                        randomNumbersThread.Resume();
                    
    else
                        randomNumbersThread.Suspend();
                }

            }


            
    private void manageTime_CheckedChanged(object sender, System.EventArgs e)
            
    {
            }


            
    private void manageNumbers_CheckedChanged(object sender, System.EventArgs e)
            
    {
            }


            
    private void manageBoth_CheckedChanged(object sender, System.EventArgs e)
            
    {
            }


            
    /**//// <summary>
            
    /// 注意其Invoke的使用,其有两种使用形式
            
    /// public void Invoke(System.Delegate delegate);
            
    /// public void Invoke(System.Delegate delegate, object [] args);
            
    /// </summary>

            public void CountTime()
            
    {
                
    while(true)
                
    {
                    Invoke(
    new UpdateTimeDelegate(updateCurrentTime));
                    Thread.Sleep(
    1000);
                }

            }


            
    public void GenerateRandomNumbers()
            
    {
                
    int [] randomNumbers = new int[10];
                Random r 
    = new Random();

                
    while(true)
                
    {
                    
    for(int i = 0; i < randomNumbers.Length; i++)
                        randomNumbers[i] 
    = r.Next(1100);

                    Invoke(
    new UpdateRandomNumbers(updateRandomNumbers), new object[] { randomNumbers });
                    Thread.Sleep(
    500);
                }

            }


            
    /**//// <summary>
            
    /// 负责更新UI界面中时间显示的函数
            
    /// </summary>

            private void updateCurrentTime()
            
    {
                currentTime.Text 
    = DateTime.Now.ToLongTimeString();
            }


            
            
    /**//// <summary>
            
    /// 负责更新UI界面中随机数显示的函数
            
    /// </summary>
            
    /// <param name="numbers"></param>

            private void updateRandomNumbers(int [] numbers)
            
    {
                System.Text.StringBuilder sb 
    = new System.Text.StringBuilder();

                
    foreach(int i in numbers)
                    sb.Append(i.ToString()).Append(
    "");

                randomNumbers.Text 
    = sb.ToString();
            }


            
    private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
            
    {
                
    if( (randomNumbersThread.ThreadState & ThreadState.Running) == ThreadState.Running )
                    randomNumbersThread.Abort();

                randomNumbersThread 
    = null;
                
                
    if( (currentTimeThread.ThreadState & ThreadState.Running) == ThreadState.Running )
                    currentTimeThread.Abort();

                currentTimeThread 
    = null;
            }

        }


        
    public delegate void UpdateTimeDelegate();
        
    public delegate void UpdateRandomNumbers(int [] numbers);
    }


       其实在C# 2.0 中所有的Control类都有Invoke()方法,如果负责更新UI元素的函数不是定义在Main()中,那么必须首先检测Control类中的InvokeRequired属性。举个例子吧,注意setProgressBarValue()函数中调用自己的方式.
            //在工作线程中更新主窗口进度条
            public void setProgressBarValue(ProgressBar progressBar1,int value)
            {
                if (progressBar1.InvokeRequired)
                {
                    object[] parameters = new object[] { value };
                    progressBar1.Invoke(new setProgressBarValueDelegate(setProgressBarValue), parameters);
                }
                else
                    progressBar1.Value = value;
            }
      这里的一些代码参考了http://www.codeproject.com  的例子.

  • 相关阅读:
    八数码难题 (codevs 1225)题解
    小木棍 (codevs 3498)题解
    sliding windows (poj 2823) 题解
    集合删数 (vijos 1545) 题解
    合并果子 (codevs 1063) 题解
    等价表达式 (codevs 1107)题解
    生理周期 (poj 1006) 题解
    区间 (vijos 1439) 题解
    区间覆盖问题 题解
    种树 (codevs 1653) 题解
  • 原文地址:https://www.cnblogs.com/chulia20002001/p/2782662.html
Copyright © 2011-2022 走看看