[英]How to create async method from sync
(下面的C#代码)
我只是想了解Async和Await。 我检查了几篇文章和教程,以为有了这个概念,但是在实现一些实际示例时似乎有些困难。
这是我的UI类的New():
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
PopulateUI()
End Sub
...所以这里的关键是PopulateUI()
。 我想使用此功能而不阻塞UI。
编译器可以接受的唯一选项是:
Private Async Sub PopulateUI()
Await Task.Run(Sub()
' Do some stuff that populates the UI comboboxes
End Sub)
End Sub
...此选项不起作用,我认为这是因为Task.Run在不同的线程中运行,因此在更新组合框时发生了奇怪的事情(抱歉,描述如此含糊,我真的不知道更好)。
因此,我发现了一个类似的SO问题 ,但没有令人满意的答案,这使我认为不是那么简单。 希望我错了。
C#版本:
public MyUI()
{
// This call is required by the designer.
InitializeComponent();
// Add any initialization after the InitializeComponent() call.
PopulateUI();
}
Private async void PopulateUI()
{
await Task.Run(() =>
{
// Do some stuff that populates the UI comboboxes
})
}
首先: 要非常小心async void ...
:这样的调用不会出现任何异常。
我不知道这是否是规范模式(如果有这样的事情),但是我通常要做的是创建一个方法void CheckResult(Task task)
,该方法使用ContinueWith
来附加必要的错误处理(通常检查是否任务故障,并记录/显示错误对话框。
然后我会做类似的事情:
public MyUI()
{
// This call is required by the designer.
InitializeComponent();
// Add any initialization after the InitializeComponent() call.
CheckResult(PopulateUI());
}
private async Task PopulateUI()
{
var data = await FetchUiData();
SetControlValues(data); // or whatever
}
private static void CheckResult(Task t) {
// We want to be doing this on the UI thread
var sched = TaskScheduler.FromCurrentSynchronizationContext();
t.ContinueWith(() => {
// check if "t" faulted and perform appropriate action
}, sched);
}
db调用应该是可以等待的,但是对于我来说,更改对我来说是非常昂贵的……所以执行fetch操作的Task.Run()是一个糟糕的主意
如您所述,理想的解决方案是使其始终处于异步状态。 因此,下面的解决方案是骇客(以避免过多的代码更改),而不是最佳实践。
也就是说,您可以在此处使用async void
和Task.Run
; 您只需要谨慎对待异常处理:
private async void PopulateUI()
{
... // Load initial view - "Loading..." message or whatever.
try
{
var data = await Task.Run(() =>
{
... // Read data from database.
});
... // Update UI with data.
}
catch (Exception ex) // Not a typo. Catch all exceptions.
{
... // Handle error - display message to user or whatever.
}
}
特别是在设置UI控件的属性时访问UI控件时使用Dispatcher ,奇怪的事情可能消失了。 从Task.Run中的任何地方获取数据,但是应该使用分派器访问在UI控件中设置属性的代码。 可能这将是您的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.