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  的例子.

  • 相关阅读:
    .Net5开发MQTT服务器
    使用Docker搭建MQTT服务器
    使用Docker搭建MQTT服务器
    在Raspberry Pi上安装Docker
    阿里云=>RHSA-2019:1884-中危: libssh2 安全更新
    MediaAPIController
    CentOS7 mysql支持中文
    设置centos7中的mysql5.7不区分表名大小写有关操作
    CentOS7 安装mysql(YUM源方式)
    centos7下安装nginx
  • 原文地址:https://www.cnblogs.com/chulia20002001/p/2782662.html
Copyright © 2011-2022 走看看