前言
多線程刷新界面主要用到多線程,委托,線程安全、事件等一系列高難度的C#操作。
1、使用timer控件對要刷新的控件進行定時刷新
對刷新頻率要求不高的時候,可以使用該方法。
2、刷新UI控件
在開發軟件時經常會需要更新界面上的某個控件來顯示相關的信息,為了讓程序執行中不出現界面卡死的現像,最好的方法就是“多線程+委托”來解決。
控件:pictureBox1
public delegate void DeleMyDelegate();//定義委托
DeleMyDelegate deleMyDelegate;//聲明委托
public void DeleMy()//定義信息函數
{
pictureBox1.Refresh();
}
public void Pic_Show()
{
deleMyDelegate = new DeleMyDelegate(DeleMy);//綁定委托
this.pictureBox1.Invoke(deleMyDelegate);
}
private void button1_Click(object sender, EventArgs e)
{
Thread myThread = new Thread(Pic_Show);
myThread.Start();
}
控件:richTextBox1
Thread myThread;
public delegate void MyDelegateUI(); //定義委托類型
MyDelegateUI myDelegateUI; //聲明委托對象
public Form1()
{
InitializeComponent();
myThread = new Thread(doWork);
myDelegateUI = new MyDelegateUI(initAll);//綁定委托
}
private void initAll() //信息處理函數定義
{
richTextBox1.AppendText("TEST line \r");
}
private void doWork()
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(100);
this.Invoke(myDelegateUI); //richTextBox1.AppendText("TEST line \r");
Application.DoEvents();
}
}
private void button1_Click(object sender, EventArgs e)
{
myThread.Start();
}
3、工作線程中刷新主界面控件狀態
(1)工作線程類
public class Work
{
private volatile static Work instanceWork; // 單例
public delegate void InvokeListBox(int i);
public InvokeListBox invokeOthers;
/// <summary>
/// 構造函數
/// </summary>
public Work()
{
}
/// <summary>
/// 對外接口,獲取單例
/// </summary>
/// <returns></returns>
public static Work GetInstance()
{
if (null == instanceWork)
{
instanceWork = new Work();
}
return instanceWork;
}
/// <summary>
/// 業務函數,在工作過程中將狀態傳給主界面
/// </summary>
public void DoSomething()
{
for (int i = 0; i < 20; i++)
{
Thread.Sleep(1000);
invokeOthers(i);
}
}
}
(2)主界面布局及代碼
private delegate void InvokeListBox(string strCon); // 刷新ListBox的委托。
private InvokeListBox invokeListBox;
private Work wk; //工作線程對象
public Form1()
{
InitializeComponent();
wk = Work.GetInstance(); //單例模式初始化工作線程對象
wk.invokeOthers = new Work.InvokeListBox(ReciveData); // 綁定,接收工作線程過來的數據
invokeListBox = new InvokeListBox(RefrushListBox); // 綁定,刷新界面ListBox控件
}
private void button1_Click(object sender, EventArgs e)
{
Thread th = new Thread(new ThreadStart(wk.DoSomething));
th.Start();
}
/// <summary>
/// 接收工作線程過來的數據,更新界面
/// </summary>
/// <param name="i"></param>
public void ReciveData(int i)
{
string strConten = i.ToString() + " 更新";
if (this.listBox1.InvokeRequired)
{
this.listBox1.Invoke(invokeListBox, new object[] { strConten });
}
}
/// <summary>
/// 具體刷新界面函數
/// </summary>
/// <param name="_str"></param>
public void RefrushListBox(string _str)
{
this.listBox1.Items.Add(_str);
}
(3)說明
本例子中有兩個委托:1、Work.cs中的委托變量 ivokeOthers,作用是將信息傳遞給給主界面對應的函數:ReceiveData()。2、Form_MainUI.cs中的委托變量 invokeListBox,作用是刷新界面控件ListBox_state的內容。點擊“開始工作”按鈕后,工作線程啟動,調用Work.cs中DoSomeThing()函數。由於Form_MainUI.cs中的函數ReceiveData()函數綁定了Work.cs中的委托ivokeOthers,所以當Work.cs中DoSomeThing被調用時ivokeOthers會把變量i傳遞給ReceiveData()。ReceiveData()接收到數據后,通過Invoke調用刷函數RefrushListBox()修改主界面ListBox_State的內容。
(4)總結
1)不要懼怕委托、事件的復雜的概念,動手操作練習一下,就簡單的把它們當做傳遞消息的載體。
2)在工作線程中修改主界面其它控件的內容、狀態、圖片等操作類似,可以自己動手試試。
3)本小結在實現刷新主界面控件的時候使用了單例模式,不使用單例模式也完全可以實現,加上單例是為了讓調用更加方便,在大項目開發中就會體現其優勢。
https://blog.csdn.net/kingshown_WZ/article/details/89322499?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param