4

我有两个列表框,一个是主人,另一个是孩子。当主节点上的索引发生变化时,子列表框会被与主节点相关的记录适当地填充。当一个主人需要很长时间才能获取所有记录并且在完成获取记录之前,用户单击另一个需要更少时间来填写的主人时,我的问题就出现了。最终会发生的情况是,即使用户不再在该主控上,花费更长时间的主控也会填充子列表框。

我一直在使用 BackgroundWorker 线程来进行填充。

bw_LoadAll.DoWork += new DoWorkEventHandler(bg_LoadAllWork);
bw_LoadAll.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_LoadAllWorkCompleted);
bw_LoadAll.WorkerSupportsCancellation = true;

我为 master 订阅了 SelectedIndexChanged 事件,并将 cancelled 设置为 true:

bw_LoadAll.CancelAsync();

这是 DoWork 方法中的代码:

List<object> s = Repository.Instance().LoadAll();
if (!bw_LoadAll.CancellationPending) {
    e.Result = s;
} else {
    e.Cancel = true;
}

但是由于某种原因,worker完成的代码不断被调用。这是工人完成的代码:

if (!e.Cancelled) {
    ddl.DataSource = e.Result;
    ddl.DisplayMember = "QuickName";
    ddl.ValueMember = "ID";
}

我还需要做些什么来取消这个线程的返回吗?

4

3 回答 3

5

您的方法 bg_LoadAllWork 应定义为:

void bg_LoadAllWork(object sender, DoWorkEventArgs e)
{
    // Do your work here...
} 

在 bg_LoadAllWork 内部,您需要检查e.CancellationPending,如果是,请设置e.Cancel = true;

最后一部分很重要 - 如果您从未设置 e.Cancel,那么您的“e.Cancelled”将永远不会等于 true。对 CancelAsync 的调用实际上并没有取消任何东西——它更像是“请求后台工作取消本身”——你必须将逻辑放在适当的位置才能导致取消。

于 2009-06-18T16:59:50.713 回答
0

从do_work 函数中的CodeProject中,您需要检查工作线程上的 CancellationPending,然后将 DoWorkEventArgs.Cancel 变量设置为 true。

于 2009-06-18T16:54:50.920 回答
0

自从我使用 BackgroundWorker 以来已经有一段时间了,但是如果我没记错的话,当您调用 时,除非 LoadAllWork 检查bw_LoadAll.CancelAsync,否则您的方法不会实际中止。LoadAllWorkbw_LoadAll.CancelationPending

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.cancelasync.aspx确认:“CancelAsync 提交终止挂起后台操作的请求并将 CancellationPending 属性设置为 true。

当您调用 CancelAsync 时,您的工作方法有机会停止其执行并退出。工作人员代码应定期检查 CancellationPending 属性以查看它是否已设置为 true。”

因此,在您的 SelectedIndexChanged 事件处理程序中,当您调用 时bw_LoadAll.CancelAsync(),它设置bw_LoadAll.CancelationPending为 true,但实际上并没有中止该LoadAllWork方法。慢加载器仍将完成。

于 2009-06-18T16:58:28.577 回答