技术开发 频道

后台线程和支持取消


    为了帮助那些在应用程序里意识到需要使用线程但不想被线程负担过重的开发者,我写了这篇文章。线程是一种难以理解、调试和实施以致很多程序员趋于避免的概念。使用C#你能开发一个复杂的多线程应用。不用担心,即使你不想花费时间去理解线程,BackgroundWorker对象也会让线程的使用变的非常容易。



代码使用

    应用程序一旦加载,它就运行在一个单线程上。这就是所说的UI线程。通常在这个线程上,创建用户界面对象以及执行完成所有的代码。用户的界面同样使用这个线程来描绘用户界面对象。所以当你运行一个长时间任务的时候,例如处理一个目录里的很多MP3文件,你的应用会锁起来,窗口变白,用户不能点击任何按纽,标题变成"My Cool App (无法响应)"。以致你返回来在MP3文件处理函数上加入一组Application.DoEvents()调用,事情会变的好一点。但这是不现实的,因为代码运行变慢,表单时而正常,时而死琐,整个应用看起来波浪起伏。

    现在你需要做的是把沉重的任务处理放在另一个线程上。让UI线程有空闲时间来描绘用户界面。.NET框架给我们提供了一个可利用的BackgroundWorker对象来简化线程使用。这个对象设计成了这样:首先在运行另一个线程上的一个函数,完成后接着调用UI线程的一个事件。具体的使用步骤也很简单,创建一个BackgroundWorker 对象,告诉它在后台线程运行哪个函数(DoWork),当后台工作完成后运行前台的哪个函数(RunWorkerCompleted),接着让BackgroundWorker 对象继续工作。

    有一个规则你需要意识到-你不能在一个不是创建用户界面对象的线程上去访问用户界面对象,如果你在DoWork函数上写下这样的代码lblStatus.Text = "Processing file 5 of 100";,你会收到一个运行时错误。有2种解决的办法,在样例中我都进行了使用。BackgroundWorker 对象提供了一个可以从后台线程的DoWork函数调用的ReportProgress函数来解决这个问题,它会触发UI线程的ProgressChanged事件。现在我们可以在自身的线程里访问UI对象、做我们想做的事情了。是否我们可以在后台线程来更新一个标签或者禁用一个按纽呢?这是没有问题的,使用Control.Invoke可以让部分代码运行在UI线程上,我在异步样例中使用这种技术来更新进度条表单的标签和进度条。
0
相关文章