从WPF视图模型中的属性设置器调用异步方法是错误的吗?

当属性更改其值时,我想调用从Web服务获取数据的异步方法,然后更新UI绑定到的另一个属性,从而导致UI更新。 我觉得更新是异步的,因为我希望UI在更新过程中保持响应。

从非异步setter调用异步方法是错误的吗? 我注意到如果异步方法返回void,那么VS不会抱怨,但如果它返回Task,那么visual studio会抱怨没有等待调用。 我的代码如下所示:

public int Property1 { set { _property1 = value; NotityPropertyChanged(); UpdateData(); } } private async void UpdateData() { // show data loading message var data = await GetDataFromWebService(); Property2 = data; // hide data loading message } 

它似乎工作,但我想知道如果返回类型为Task,如果我从VS获得警告,我是否按照预期的方式使用异步。

更新:一些答案和评论建议用户使用命令而不是更新以响应属性的更改。 对于我的情况,我不确定如何应用,所以提供有关UI如何工作的更多细节。

在用户界面中,有日期选择器(绑定到视图模型上有问题的属性),用户在该日期选择器中选择要查看记录的日期。 当用户选择新日期时,应用程序应显示忙碌指示符,然后在后台获取记录以避免阻止UI线程。 优选地,我希望在选择日期时启动更新,而不需要用户在选择日期之后按下按钮。

将日期选择器的SelectionChanged事件绑定到ViewModel上的async命令或者是否具有SelectionChanged的同步处理程序更好,它会直接调用视图模型上的update方法吗?

从非异步setter调用异步方法是错误的吗?

简而言之,是的。 属性不应该在其setter中启动异步后台操作。

我建议你阅读Stephen Cleary关于这个主题的博文和MSDN文章:

异步编程:异步MVVM应用程序的模式:数据绑定: https //msdn.microsoft.com/en-us/magazine/dn605875.aspx

异步OOP 3:属性: https //blog.stephencleary.com/2013/01/async-oop-3-properties.html

您可能还想查看一个function性MVVM框架,例如ReactiveUI ,它通过将属性转换为您可以订阅的可观察值的流来处理此场景: https : //reactiveui.net/docs/getting-started/

这不是已经说过的“最干净”的方式,但你可以放弃它。 除了你在快速任务背后隐藏一个意想不到的长而昂贵的操作之外,它首先没有害处。

MSDN说 :

异步方法也可以具有void返回类型。 此返回类型主要用于定义事件处理程序,其中需要void返回类型。 异步事件处理程序通常用作异步程序的起点。

无法等待具有void返回类型的异步方法,并且void返回方法的调用方无法捕获该方法抛出的任何exception。

一个简单的解决方案可能是收听PropertyChanged事件。 这更像是逃避制定者的工作。 更好的方法是通过向其添加异步执行来实现ICommand接口asynchrounous,从而使ViewModel公开更新命令。 然后,只要属性发生更改,您就可以从View中调用此AsyncCommand。 您还可以将新值作为命令参数传递给ViewModel。

仅在属性更改时自动调用更新通常是一个坏主意。
通常,按钮和命令是更好的计划。 您也可以从UI调用命令而不是使用该setter。 这样做比较简单。

至少,您需要一个不同的线程来以某种方式调用某些Web服务。
火与遗忘的线程并不完全是可怕的。
只要你不在乎忘记它后会发生什么。