C# 我应该如何从任务更新 UI 线程?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14620060/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How should I update from Task the UI Thread?
提问by Night Walker
I have a task that performing some heavy work.
I need to path it's result to LogContent
我有一项任务需要执行一些繁重的工作。我需要将它的结果传递给LogContent
Task<Tuple<SupportedComunicationFormats, List<Tuple<TimeSpan, string>>>>.Factory
.StartNew(() => DoWork(dlg.FileName))
.ContinueWith(obj => LogContent = obj.Result);
This is the property:
这是物业:
public Tuple<SupportedComunicationFormats, List<Tuple<TimeSpan, string>>> 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);
}
}
}
Problem is that _traceEntryQueue
is data bound to UI, and of cause I will have exception on code like this.
问题是_traceEntryQueue
数据绑定到 UI,因此我会对这样的代码产生异常。
So, my question is how to make it work correctly?
所以,我的问题是如何使其正常工作?
采纳答案by bobblez
You need to run the ContinueWith -task on the UI thread. This can be accomplished using the TaskScheduler of the UI thread with the overloaded version of the ContinueWith -method, ie.
您需要在 UI 线程上运行 ContinueWith -task。这可以使用 UI 线程的 TaskScheduler 和ContinueWith 方法的重载版本来完成,即。
TaskScheduler scheduler = TaskScheduler.Current;
...ContinueWith(obj => LogContent = obj.Result), CancellationToken.None, TaskContinuationOptions.None, scheduler)
回答by RePierre
You can use the Dispatcher
to invoke code on UI thread. Take a look at the article Working With The WPF Dispatcher
您可以使用Dispatcher
来调用 UI 线程上的代码。看一下使用 WPF Dispatcher的文章
回答by Sergey Brunov
Here is a good article: Parallel Programming: Task Schedulers and Synchronization Context.
这是一篇很好的文章:并行编程:任务调度程序和同步上下文。
Take a look at Task.ContinueWith() method.
Example:
例子:
var context = TaskScheduler.FromCurrentSynchronizationContext();
var task = new Task<TResult>(() =>
{
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();
Since .NET 4.5 supports async
/await
keywords (see also Task.Run vs Task.Factory.StartNew):
由于 .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.
}
回答by Contango
If you are using async/await, then here is some example code that shows how to schedule a task to run on the GUI thread. Place this code at the bottom of the stack of all of your async/await calls to avoid the WPF runtime throwing errors with code not executing on the GUI thread.
如果您正在使用 async/await,那么这里是一些示例代码,展示了如何安排在 GUI 线程上运行的任务。将此代码放在所有 async/await 调用的堆栈底部,以避免 WPF 运行时因代码不在 GUI 线程上执行而引发错误。
Works with WPF + MVVM, tested under VS 2013.
与 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;
}