2012-04-23 83 views
4

我正在使用Winform应用程序。 Method由一个BackgroundWorker线程启动。对不起。我之前没有提到这一点。从任务更新UI标签。继续

private void Method() 
{ 
tasks[i] = Task.Factory 
      .StartNew(() => fileProcessor.ProcessEachMachine(mdetail)) 
      .ContinueWith(UpdateLabel, TaskContinuationOptions.OnlyOnRanToCompletion); 
} 

我有一个长时间的运行功能ProcessEachMachine。在继续功能UpdateLabel我想访问UIlabel并更新状态。

private void UpdateLabel() 
{ 
    progressLbl.Text = "updated"; 
} 

但标签没有更新。如何访问UILabel并更新它的文本。

+0

确定'ProcessEachMachine'之前完成更新标签?也许任务运行很长时间,很长时间 – GETah 2012-04-23 18:11:06

+1

ContinueWith是什么保证?假设我错了吗? – Sandeep 2012-04-23 18:12:22

+0

@Sandeep不,你没有错。你只需要确保你回到UI线程。 – Servy 2012-04-23 18:19:41

回答

8

您必须在ContinueWith上设置TaskScheduler.FromCurrentSynchronizationContext,否则它将不会在UI上下文中运行。 Here is the MSDN on the override that you must use for this call to ContinueWith

它应该结束这样看:

.ContinueWith(UpdateLabel, null, 
    TaskContinuationOptions.OnlyOnRanToCompletion, 
    TaskScheduler.FromCurrentSynchronizationContext()); 

它可能看起来像什么也没发生,但TPL正在吞噬你的跨线程异常。如果您不打算检查每个结果或检查其异常,则应该使用UnobservedTaskException。否则,当发生垃圾收集时,会发生异常,然后......可能很难调试错误。

更新基于你的主要任务是建立更新

,并通过一个BackgroundWorker开始,我的主要问题是,为什么这不能用一个任务开始?事实上,如果Method中没有更多,那么这真的只是双重工作,可能会混淆其他开发人员。你已经异步启动了,为什么不在背景工作中做你的工作,并使用UpdateLabel(作为后台工作人员已经了解情境)的方法。

的主要问题仍然是,虽然是相同的,所以这里有一些其他的解决方案,如果你觉得你必须使用TPL:

  1. 您可以Invoke返回到主UI线程UpdateLabel方法中
  2. 您可以将当前上下文传递到后台工作,然后使用它替换
  3. 您可以Wait为您的原始任务返回,然后使用worker的oncomplete事件更新标签。

这里是我会怎么做这个(所有伪代码)

后台工作方法:

Method() called because of Background worker 

private void Method() 
{ 
    fileProcessor.ProcessEachMachine(mdetail); 
} 

Wire up background worker's OnRunWorkerCompleted: 

if(!e.Cancelled && !e.Error) 
    UpdateLabel(); 

任务唯一方法

Call Method() from the main thread and just let the TPL do its work :) 

Task.Factory.StartNew(() => fileProcessor.ProcessEachMachine(mdetail)) 
     .ContinueWith((precedingTask)=>{if(!precedingTask.Error)UpdateLabel;}, 
      null, TaskContinuationOptions.OnlyOnRanToCompletion, 
      TaskScheduler.FromCurrentSynchronizationContext()); 
+0

对不起。我已经纠正了这个问题。 – Sandeep 2012-04-23 18:57:41

+0

@Sandeep更新了我的回复......很奇怪,你有什么解决方案...... – 2012-04-23 19:07:10

+0

我这样做的原因是我必须连接到db,获取机器列表,然后搜索所有这10台机器。如果有更好的方法来做到这一点,我很乐意学习。 – Sandeep 2012-04-23 19:21:01