2009-06-18 61 views
4

我有两个列表框,一个是主人,另一个是孩子。当主索引上的索引发生变化时,子列表框将被正确填充与主索引有关的记录。当一位主人花费很长时间获取所有记录,并且在完成获取记录之前,用户点击另一位需要较少时间填写的主人,我的问题即将到来。发生的是,最终,即使用户不在该主人身上,花费较长时间的主人也会填充子列表框。取消winforms中的工作线程

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

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

我订阅了SelectedIndexChanged事件的主人和我设置取消等于真:

bw_LoadAll.CancelAsync(); 

这里是在DoWork的方法的代码:

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

但对于某种原因,工作人员完成的代码不断被调用。这里是工作人员完成代码:

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

有没有别的东西,我必须做的,从返回取消这个线程?

回答

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的调用实际上并不会取消任何内容 - 更像是“请求后台工作取消” - 您必须将逻辑放置到导致取消的位置。

+0

CancellationPending未公开在DoWorkEventArgs上,而不是在BackgroundWorker上显示,在此示例中该参数为参数。 – Sherlock 2010-10-02 05:47:24

0

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

+0

如果我在点击主项目之间花费时间,那么这个方法就行得通,但如果我点击一下,然后点击另一个点击,它似乎不会及时设置。我将更新代码以显示我在工作方法中所做的工作。 – Josh 2009-06-18 16:58:31

0

它是因为我已经使用了BackgroundWorker的一段时间,但如果我没有记错,当你调用bw_LoadAll.CancelAsync,还有你LoadAllWork方法没有实际的流产,除非LoadAllWork检查bw_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为真,但它实际上没有中止LoadAllWork方法。慢加载程序仍将完成。