65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 BackgroundWorker 进行异步调用

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.72/5 (9投票s)

2006年7月20日

2分钟阅读

viewsIcon

73218

downloadIcon

2196

一篇关于在 C# 中实现异步代码的简单文章。

Sample Image

引言

当您有一个需要很长时间的函数并且它会冻结屏幕时,用户会感到不安。他们 просто 不喜欢失去控制。当他们仍然可以单击表单,而应用程序正忙于获取信息时,例如,这会给人留下友好的印象。当您开始实现异步方法时,您会想知道哪种技术最适合您的应用程序。您会使用 Timer 类、Thread 类还是 BackgroundWorker?本文使用 BackgroundWorker 类来展示它有多么容易,以及使用它时需要注意的地方。

背景

我尝试在我的 网络日志中比较实现异步调用的不同方法。使用 Microsoft Visual Studio 2005,我发现了这个对我来说是新的类。

使用代码

我在所有可能的地方都添加了额外的注释,以使该示例成为您可以用来开始您自己的实现的代码片段。该代码实现了一个非常简单的操作,即在目录中查找文件以模拟耗时的操作。这是您需要更改的地方。对于其余部分,骨架应保持不变。

后台工作程序能够向被调用的线程发送事件以更改屏幕外观。这非常容易,我认为每个人都会很容易发现。但是,如果这还不够,并且您想将其他消息发送回调用者怎么办?所以我使用 BeginInvoke 在调用者线程上调用一个调用。

我有两个从子线程使用的委托,用于调用主线程中实现的方法。

private delegate void PaintMessage(TreeNode root, 
                                   string childText);
private PaintMessage myAddNode = null;

OnPaontMessage 实现了将新找到的文件添加到现有(给定)根目录中。当子线程找到新项目时会调用此方法。

private delegate void EnableCancel(bool enabled);
private EnableCancel myEnableCancel = null;

第二个委托指示线程已启动并且可以停止。它由主线程实现以启用“取消”按钮。

启动操作将通过调用工作程序上的 RunWorkerAsync 方法来完成。

this.backgroundWorker1.RunWorkerAsync(treeView1.Nodes[path]);

当找到一个子文件夹时,我向主线程发送一个通知,以便为主线程创建一个节点。 然后,我使用该节点在其中创建一个文件节点。 但是,进退两难的是,如果主线程没有机会创建子文件夹,我将无法继续填写文件。 因此,我需要等待并让主应用程序有机会创建它。 一种简单的方法是以下循环

// Create a folder node before proceeding
IAsyncResult ar = BeginInvoke(myAddNode, new object[]
                  { root, di.Name });
// Update the screen

// Wait until the folder has been created before
// proceeding with the content of the folde
while (!ar.IsCompleted)
{
    Application.DoEvents();
    ar.AsyncWaitHandle.WaitOne(-1, false);
}

首先,我调用委托并保留对它的引用。 我使用该引用来查看它是否已完成。 在循环中,我让应用程序有机会并执行其事件。 同时,我告诉我的子线程稍等片刻。

© . All rights reserved.