C#后台线程和UI的交互 (转)

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

转载于:https://www.cnblogs.com/ztotem/archive/2008/10/03/1303603.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值