日期:2014-05-17  浏览次数:21112 次

C# 多线程控制控件实例(例程简单,注释详细)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace treadTest
{???
??? //定义委托
??? public delegate void ListBoxDelegate();
??? public partial class Form1 : Form
??? {
??????? public Form1()
??????? {
??????????? InitializeComponent();
??????? }
??????? //委托处理方法(关联与ListBoxDelegate)
??????? private void ListBox()
??????? {
??????????? if (!listBox1.InvokeRequired)//如果在UI主线程操作ListBox,
??????????? {
??????????????? listBox1.Items.Add(++CommonData.num);//则直接进行控件操作,“与UI主线程相关联”
??????????????? listBox1.SelectedItem = listBox1.Items[listBox1.Items.Count - 1];
??????????? }
??????????? else//如果是在另一线程操作ListBox,则启用委托
??????????????? listBox1.Invoke(new ListBoxDelegate(listShow));
??????? }
???????
??????? //定义对UI主线程控件的操作,“与AddAuto相关联”。
??????? private void listShow()
??????? {
??????????? listBox1.Items.Add(CommonData.num);
??????????? listBox1.SelectedItem = listBox1.Items[listBox1.Items.Count - 1];
??????? }
??????? //定义线程函数
??????? private void AddAuto()
??????? {
??????????? while (CommonData.Flag == 0)
??????????? {
??????????????? CommonData.num++;
??????????????? Thread.Sleep(1000);
??????????????? ListBox();//不能直接控制UI上的控件,所以用该方法选择使用委托
??????????? }
??????? }
??????? //在click事件中启动多线程
??????? private void btnStart_Click(object sender, EventArgs e)
??????? {
??????????? //线程标志置0,表示开启线程
??????????? CommonData.Flag = 0;
??????????? //定义 ThreadStart的委托类型的参数,并使该委托指向线程函数
??????????? ListBoxDelegate mycn = new ListBoxDelegate(AddAuto);
??????????? //实例化线程
??????????? Thread insertTxt = new Thread(new ThreadStart(mycn));
??????????? //启动线程
??????????? insertTxt.Start();?????
??????? }

??????? private void btnAbort_Click(object sender, EventArgs e)
??????? {
??????????? CommonData.Flag = 1;
??????? }
??????? private void btnCtrlMain_Click(object sender, EventArgs e)
??????? {
??????????? ListBox();
??????? }
??????? private void btnReset_Click(object sender, EventArgs e)
??????? {
??????????? CommonData.num = 0;
??????? }
??????? private void btnClear_Click(object sender, EventArgs e)
??????? {
??????????? listBox1.Items.Clear();
??????? }
??????? private void btnQuit_Click(object sender, EventArgs e)
??????? {
??????????? Application.Exit();
??????? }


??? }
???
??? //全局变量解决方案
??? public class CommonData
??? {
??????? private static int _Flag = 0;
??????? private static int _num = 0;
??????? public static int Flag
??????? {
??????????? get { return _Flag; }
??????????? set { _Flag = value; }
??????? }
??????? public static int num
??????? {
??????????? get { return _num; }
??????????? set { _num = value; }
??????? }
??? }
}

?

总结:

??????? 要使用多线程控制UI控件,必须用委托实现。调用控件的Invoke方法(Invoke方法的参数是一个委托类型的参数)。

实现步骤:

???????? 1.声明委托。

????????? 2.声明委托处理函数(判断是主线程控制UI控件,还是Invoke(多线程)控制UI控件)。

???????? 3.声明一个线程实例,将线程函数的委托传入ThreadStart()。

???????? 4.开启该线程。

???????? 5.定义该线程函数,欲控制UI控件,则调用第2步的委托处理函数,他将自己判断选择用Invoke。

???????? 6.定义Invoke需要调用的函数(如本例的listShow函数)

//*********************************************************************************************************************************

????? 在上例中,只是完成了多线程控制主线程控件的功能,如果能手动和自动同时访问全局变量时,就有可能出现线程不同步的问题。以下主要利用lock线程锁来修改解决方案,使线程同步,注意代码带动的地方。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace treadTest
{???
??? //定义委托
??? public delegate void ListBoxDelegate();