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();
}
}
}
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; }
}
}
}
總結:
要使用多線程式控制制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("使用多線程");
}
}
}