c# 多线程界面卡顿_C# Winform 多线程更新界面UI控件,解决界面卡顿问题

前言

多线程刷新界面主要用到多线程,委托,线程安全、事件等一系列高难度的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;

/// /// 构造函数

///

public Work()

{

}

/// /// 对外接口,获取单例

///

///

public static Work GetInstance()

{

if (null == instanceWork)

{

instanceWork = new Work();

}

return instanceWork;

}

/// /// 业务函数,在工作过程中将状态传给主界面

///

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();

}

/// /// 接收工作线程过来的数据,更新界面

///

///

public void ReciveData(int i)

{

string strConten = i.ToString() + " 更新";

if (this.listBox1.InvokeRequired)

{

this.listBox1.Invoke(invokeListBox, new object[] { strConten });

}

}

/// /// 具体刷新界面函数

///

///

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)本小结在实现刷新主界面控件的时候使用了单例模式,不使用单例模式也完全可以实现,加上单例是为了让调用更加方便,在大项目开发中就会体现其优势。

你可能感兴趣的:(c#,多线程界面卡顿)