wpf C# 在任务中更新 UI
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38829873/
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
C# Update UI In Task
提问by Varun Jain
I am new to C#Taskand threading.
我是新手C#Task和线程。
I have a code like below:-
我有一个像下面这样的代码:-
public void UpdateSales(object sender, EventArgs args)
{
Task.Run(() =>
{
// Some code Create Collection ...
// Some code with business logic ..
// Below code is to update UI
// is it safe to update UI like below
saleDataGrid.Dispatcher.Invoke((Action) (() =>
{
saleDataGrid.ItemsSource = currentCollection;
saleDataGrid.Items.Refresh();
}));
});
}
I am not sure if this code is correct or not. I am think in any case deadlock can occur?
我不确定此代码是否正确。我认为在任何情况下都会发生死锁?
Can you please point how can i update UI from Task? i am not using async/awaitbecause UpdateSalesis event handler from third party library.
你能指出我如何从任务更新用户界面吗?我没有使用,async/await因为UpdateSales是来自第三方库的事件处理程序。
回答by slugster
As you know, Task.Runwill execute on a threadpool thread.
You can then use a ContinueWithwhich will run at the completion of that task - and if you choose one of the overridesthat allows you to specify a TaskScheduler then you can use TaskScheduler.FromCurrentSynchronizationContext()which will use the synchronization context that you entered the method on - if that is a UI thread (for example you are in an event handler for a UI event) then the synchronization context will be that of the UI thread.
然后,您可以使用将在该任务完成时运行的ContinueWith- 如果您选择允许您指定 TaskScheduler的覆盖之一,那么您可以使用TaskScheduler.FromCurrentSynchronizationContext()它将使用您输入的同步上下文方法 - 如果这是一个 UI 线程(例如,您在 UI 事件的事件处理程序中),那么同步上下文将是 UI 线程的同步上下文。
So your code will look something like this:
所以你的代码看起来像这样:
Task.Run(() => {
...code to create collection etc...
}
)
.ContinueWith(() => {
saleDataGrid.ItemsSource = currentCollection;
}
, TaskScheduler.FromCurrentSynchronizationContext()
);
回答by Stephen Cleary
Assuming that UpdateSalesis called on the UI thread, a cleaner solution would be this:
假设UpdateSales在 UI 线程上调用,一个更简洁的解决方案是这样的:
public async void UpdateSales()
{
var collection = await Task.Run(() =>
{
// Some code Create Collection ...
// Some code with business logic ..
return currentCollection;
});
saleDataGrid.ItemsSource = collection;
saleDataGrid.Items.Refresh();
}
As I describe on my blog, the awaitwill automatically resume on a captured context(in this case, the UI context). I much prefer using the implicit context of awaitrather than Dispatcherdirectly: the code is shorter and more portable.
正如我在我的博客中所描述的,await将在捕获的上下文(在本例中为 UI 上下文)上自动恢复。我更喜欢使用隐式上下文await而不是Dispatcher直接使用:代码更短且更便携。

