上一节讲到在实际的编程中某些任务执行完成时间可能较长,比如打开大文件、连接远程计算机或查询数据库,这个时候可能会导致UI界面发生长时间未响应,如果你需要在执行某些任务的同时,还要进行UI界面的响应,BackgroundWorker是您最好的选择,同时,从VS2005开始也BackgroundWorker组件,这使Backgroundworker使用起来更加的方便。
下面我会通过一个更新UI界面进度条的例子来向大家逐步的讲解BackgroundWorker类
首先新建一个Form应用程序,在UI也添加一个按钮和一个进度条processbar
如图所示:
然后进入.cs页
先声明一个全局的BackgroundWorker 实例
Private BackgroundWorker backgroundWorker = new BackgroundWorker();
private static int sum = 0;//定义一个全局的sum,下边函数计数用
然后在Buntton_Click(object sender, EventArgs e)
{
//DoWork 事件在调用RunWorkerAsync()函数时发生,该事件是在另一个线程里执行的,该线程属于线程池中的一个线程。所以,不能在这个事件中操作UI元素
backgroundworker.DoWork += new DoWorkEventHandler(backgroundworker_DoWork);
//触发DoWork事件,同时RunWorkerAsync的参数即为DoWork()函数所需的参数,如果参数过多,可以先将参数封装成类,再进行传递
backgroundworker.RunWorkerAsync(10);
//获取或设置一个值,该值指示BackgroundWorker能否报告进度更新,在用于更新进度条等的操作中,需要将该值设置为true backgroundworker.WorkerReportsProgress = true;
//在实际使用中往往使用给方法和事件更新进度条或者日志信息,通过ReportProgress()来触发该事件 backgroundworker.ProgressChanged+=new ProgressChangedEventHandler(backgroundworker_ProgressChanged);
//后台操作结束、或取消、异常等会触发该事件,相当于委托中AsyncCallback事件,该事件是在创建控件的线程中执行的
backgroundworker.RunWorkerCompleted+=new RunWorkerCompletedEventHandler(backgroundworker_RunWorkerCompleted);
}
//随时的显示更新进度
void backgroundworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;//随着后台操作的执行,不断的更新进度
}
//在后台任务执行完之后,将进程条的设为100
Void backgroundworker_RunWorkerCompleted(objec tsender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("求和结果为:" + sum+"当前的线程为:"+Thread.CurrentThread.ManagedThreadId);
progressBar1.Value = 100;
}
//该事件中进行耗时的操作,但是不要涉及对UI元素的操作
void backgroundworker_DoWork(object sender, DoWorkEventArgs e)
{
MessageBox.Show("DoWork所在的线程为:" + Thread.CurrentThread.ManagedThreadId+"是否为后台线程:"+Thread.CurrentThread.IsBackground);
int a = (int)e.Argument;
for (int i = 1; i <= a; i++)
{
sum += i;
Thread.Sleep(500);
//通过执行该方法,触发ProgressChanged事件,不断的更新processbar的值
backgroundworker.ReportProgress(sum); }
}
实验结果如下:
通过以上这个例子,相信你基本已经可以自主的运用BackgroundWorker类了,最后再将BackgroundWorker类进行一个总结:
BackgroundWorker对象有三个主要的事件:
DoWork - 当BackgroundWorker对象的多线程操作被执行时触发。
RunWokerCompleted - 当BackgroundWoker对象的多线程操作完成时触发。
ProgressChanged - 当BackgroundWorker对象的多线程操作状态改变时触发。
如果想让BackgroundWorker对象以异步的方式报告线程实时进度,必须将属性WorkerReportsProgress的值设为true。BackgroundWorker对象的ReportProgress方法用于向主线程返回后台线程执行的实时进度。
关于BackgroundWorker就介绍到这里,下面介绍Timer类
Timer类
关于Timer类.NET中有三个Timer,分别是: System.Windows.Forms.Timer,System.Timers.Timer,System.Threading.Timer 。
System.Windows.Forms.Timer主要用于依赖于WinForm程序中的窗体,Timer代码直接运行于UI线程中,所以可以操作UI控件。
System.Timers.Timer可以用在Component 或者一般的类里,该Timer的事件默认执行线程池中一个线程,如果需要让代码执行在某个特定线程中,需要通过设置Timer的SynchronizingObject 属性。
System.Threading.Timer,可以在任何多线程环境中使用Timer,该事件也是在线程池中的线程上执行的。
System.Timers.Timer应用示例:
先将Form窗体中放置一个Button,将Button的Text属性设为Timer,
在Button_Click(object sender, EventArgs e)
{
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = 1000;//设置Interval属性,每隔多少秒就触发Tick事件
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
button8.Text = DateTime.Now.ToLocalTime().ToString();
}
通过System.Windows.Forms.Timer可以很容易的操作Ui界面的控件,比如本例可以通过Button的Text属性来显示当前的时间。
实验结果如下:
System.Threading.Timer示例:
Button_Click(object sender, EventArgs e)
{
//System.Threading.Timer的构造函数有5个重载,基本上都差不多。第一个参数为一个TimerCallback的委托,第二个参数为委托调用函数所需的参数,如果没有可以设置为null,第三个为调用callback之前的延迟时间,第四个调用callback的时间间隔。
System.Threading.Timer timer1 = new System.Threading.Timer(new TimerCallback(Count), 10, 5000, 10);
}
Private static void Count(object obj)
{
Int a=(int)obj;
For(int i=0;i<a;i++)
{
Sum+=1;
}
MessageBox.Show("Sum的值:"+sum);
}
实验结果:因为每个10毫秒就要触发一个Count事件,所以会一直不停的弹出MessageBox,sum是一个全局变量,所以会不断的累加。
关于System.Timers.Timer就不再过多的介绍了,希望有兴趣的朋友下去自己了解。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构