View Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication2
{
//定义委托
public delegate void ListBoxDelegate();
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
//委托处理方法(关联与ListBoxDelegate)
private void ListBox()
{
if (!listBox1.InvokeRequired)//如果在UI主线程操作ListBox,
{
//listBox1.Items.Add(++CommonData.num);//则直接进行控件操作,“与UI主线程相关联”
listBox1.Items.Add(CommonData.plus());//则直接进行控件操作,“与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.Items.Add(CommonData.plus());
listBox1.SelectedItem = listBox1.Items[listBox1.Items.Count - 1];
}
//定义线程函数
private void AddAuto()
{
while (CommonData.Flag == 0)
{
//CommonData.num++;
Thread.Sleep(1000);
ListBox();//不能直接控制UI上的控件,所以用该方法选择使用委托
}
}
/// <summary>
/// 在click事件中启动多线程
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStart_Click_1(object sender, EventArgs e)
{
CommonData.Flag = 0;//线程标志置0,表示开启线程
ListBoxDelegate mycn = new ListBoxDelegate(AddAuto);//定义 ThreadStart的委托类型的参数,并使该委托指向线程函数
Thread insertTxt = new Thread(new ThreadStart(mycn));//实例化线程
insertTxt.Start();//启动线程
}
private void btnAbort_Click_1(object sender, EventArgs e)
{
CommonData.Flag = 1;
}
private void btnCtrlMain_Click_1(object sender, EventArgs e)
{
ListBox();
}
private void btnReset_Click_1(object sender, EventArgs e)
{
CommonData.num = 0;
}
private void btnClear_Click_1(object sender, EventArgs e)
{
listBox1.Items.Clear();
}
private void btnQuit_Click_1(object sender, EventArgs e)
{
Application.Exit();
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication2
{
//定义委托
public delegate void ListBoxDelegate();
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
//委托处理方法(关联与ListBoxDelegate)
private void ListBox()
{
if (!listBox1.InvokeRequired)//如果在UI主线程操作ListBox,
{
//listBox1.Items.Add(++CommonData.num);//则直接进行控件操作,“与UI主线程相关联”
listBox1.Items.Add(CommonData.plus());//则直接进行控件操作,“与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.Items.Add(CommonData.plus());
listBox1.SelectedItem = listBox1.Items[listBox1.Items.Count - 1];
}
//定义线程函数
private void AddAuto()
{
while (CommonData.Flag == 0)
{
//CommonData.num++;
Thread.Sleep(1000);
ListBox();//不能直接控制UI上的控件,所以用该方法选择使用委托
}
}
/// <summary>
/// 在click事件中启动多线程
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStart_Click_1(object sender, EventArgs e)
{
CommonData.Flag = 0;//线程标志置0,表示开启线程
ListBoxDelegate mycn = new ListBoxDelegate(AddAuto);//定义 ThreadStart的委托类型的参数,并使该委托指向线程函数
Thread insertTxt = new Thread(new ThreadStart(mycn));//实例化线程
insertTxt.Start();//启动线程
}
private void btnAbort_Click_1(object sender, EventArgs e)
{
CommonData.Flag = 1;
}
private void btnCtrlMain_Click_1(object sender, EventArgs e)
{
ListBox();
}
private void btnReset_Click_1(object sender, EventArgs e)
{
CommonData.num = 0;
}
private void btnClear_Click_1(object sender, EventArgs e)
{
listBox1.Items.Clear();
}
private void btnQuit_Click_1(object sender, EventArgs e)
{
Application.Exit();
}
}
}
View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WindowsFormsApplication2
{
class CommonData
{
private static int _Flag = 0;
private static int _num = 0;
//CommonData.num只是完成了多线程控制主线程控件的功能,
//如果能手动和自动同时访问全局变量时,就有可能出现线程不同步的问题。
//以下主要利用lock线程锁来修改解决方案,使线程同步
public static int plus()
{
lock (new object())
{
return _num++;
}
}
public static int Flag
{
get { return _Flag; }
set { _Flag = value; }
}
public static int num
{
get { return _num; }
set { _num = value; }
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WindowsFormsApplication2
{
class CommonData
{
private static int _Flag = 0;
private static int _num = 0;
//CommonData.num只是完成了多线程控制主线程控件的功能,
//如果能手动和自动同时访问全局变量时,就有可能出现线程不同步的问题。
//以下主要利用lock线程锁来修改解决方案,使线程同步
public static int plus()
{
lock (new object())
{
return _num++;
}
}
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线程锁来修改解决方案,使线程同步,注意代码带动的地方。
转 http://www.cnblogs.com/kingkoo/archive/2009/05/02/1447728.html
C#多线程中使用代理(委托)
http://blog.163.com/zhb123@126/blog/static/62515850201062714121186/
View Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication2
{
public delegate void myDelegate1(string s);//1.定义委托
public partial class TestThread : Form
{
public TestThread()
{
InitializeComponent();
}
//2.为修改进度条创建一个方法:
private void SetProgressBar1(string s)
{
progressBar1.Value = 0;
progressBar1.Maximum = 2;
this.progressBar1.Value = this.progressBar1.Value + 1;
MessageBox.Show("SetProgressBar1"+s);
}
//3.创建一个新线程并指向“TRun1”方法
private void TRun1()
{
// 判断控件是否属于该线程
//判断控件是否在本线程内
if (!this.progressBar1.InvokeRequired)
{
Thread.Sleep(2000);
}
else
{
myDelegate1 md1 = new myDelegate1(SetProgressBar1);//不属于该线程,创建一个代理,并将代理指向“SetProgressBar1”方法
Thread.Sleep(2000);//停顿2秒钟
//Invoke(md1);//Invoke代理,从而执行“SetProgressBar1”方法。(“SetProgressBar1”方法在主线程地址空间执行)
Invoke(md1, "TRun1");
}
}
//4.开启新线程调用:
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(TRun1));
thread.Start();
MessageBox.Show("使用多线程");
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication2
{
public delegate void myDelegate1(string s);//1.定义委托
public partial class TestThread : Form
{
public TestThread()
{
InitializeComponent();
}
//2.为修改进度条创建一个方法:
private void SetProgressBar1(string s)
{
progressBar1.Value = 0;
progressBar1.Maximum = 2;
this.progressBar1.Value = this.progressBar1.Value + 1;
MessageBox.Show("SetProgressBar1"+s);
}
//3.创建一个新线程并指向“TRun1”方法
private void TRun1()
{
// 判断控件是否属于该线程
//判断控件是否在本线程内
if (!this.progressBar1.InvokeRequired)
{
Thread.Sleep(2000);
}
else
{
myDelegate1 md1 = new myDelegate1(SetProgressBar1);//不属于该线程,创建一个代理,并将代理指向“SetProgressBar1”方法
Thread.Sleep(2000);//停顿2秒钟
//Invoke(md1);//Invoke代理,从而执行“SetProgressBar1”方法。(“SetProgressBar1”方法在主线程地址空间执行)
Invoke(md1, "TRun1");
}
}
//4.开启新线程调用:
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(TRun1));
thread.Start();
MessageBox.Show("使用多线程");
}
}
}