我应该如何从任务UI线程更新?

我有一项任务,执行一些繁重的工作。 我需要将它的结果LogContentLogContent

 Task<Tuple<SupportedComunicationFormats, List<Tuple>>>.Factory .StartNew(() => DoWork(dlg.FileName)) .ContinueWith(obj => LogContent = obj.Result); 

这是属性:

 public Tuple<SupportedComunicationFormats, List<Tuple>> LogContent { get { return _logContent; } private set { _logContent = value; if (_logContent != null) { string entry = string.Format("Recognized {0} log file",_logContent.Item1); _traceEntryQueue.AddEntry(Origin.Internal, entry); } } } 

问题是_traceEntryQueue是绑定到UI的数据,因为我会在这样的代码上有exception。

所以,我的问题是如何让它正常工作?

您需要在UI线程上运行ContinueWith -task。 这可以使用UI线程的TaskScheduler和ContinueWith -method的重载版本来完成 ,即。

 TaskScheduler scheduler = TaskScheduler.Current; ...ContinueWith(obj => LogContent = obj.Result), CancellationToken.None, TaskContinuationOptions.None, scheduler) 

这是一篇好文章: 并行编程:任务调度程序和同步上下文 。

看看Task.ContinueWith()方法 。

例:

 var context = TaskScheduler.FromCurrentSynchronizationContext(); var task = new Task(() => { TResult r = ...; return r; }); task.ContinueWith(t => { // Update UI (and UI-related data) here: success status. // t.Result contains the result. }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, context); task.ContinueWith(t => { AggregateException aggregateException = t.Exception; aggregateException.Handle(exception => true); // Update UI (and UI-related data) here: failed status. // t.Exception contains the occured exception. }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, context); task.Start(); 

由于.NET 4.5支持async / await关键字(另请参阅Task.Run与Task.Factory.StartNew ):

 try { var result = await Task.Run(() => GetResult()); // Update UI: success. // Use the result. } catch (Exception ex) { // Update UI: fail. // Use the exception. } 

您可以使用Dispatcher在UI线程上调用代码。 看一下使用WPF Dispatcher的文章

如果您使用的是async / await,那么这里有一些示例代码,说明如何安排在GUI线程上运行的任务。 将此代码放在所有async / await调用的堆栈底部,以避免WPF运行时因未在GUI线程上执行的代码而抛出错误。

适用于WPF + MVVM,在VS 2013下测试。

 public async Task GridLayoutSetFromXmlAsync(string gridLayoutAsXml) { Task task = new Task(() => // Schedule some task here on the GUI thread ); task.RunSynchronously(); await task; }