简体   繁体   English

使用MVVM模式实现异步“loadData”方法的最佳方法

[英]Best way to implement an async “loadData” method using the MVVM pattern

I'm trying to understand what is the best approach to use when calling an async method that updates my ViewModel. 我试图了解在调用更新我的ViewModel的异步方法时使用的最佳方法是什么。 Right now, let's say I have something like this: 现在,让我说我有这样的事情:

View: 视图:

private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
    //Call my ViewModel method to update the data the UI is bound to          
}

ViewModel: 视图模型:

public async Task loadData()
{
    this.Source = await loadStuffFromDatabaseAsync();
}

Now, I'm not sure which one of the following approaches should I use: 现在,我不确定应该使用以下哪种方法:

1) In my LoadState method, use: 1)在我的LoadState方法中,使用:

await Task.Run(async () => { await ViewMode.loadData(); });

2) Use Task.Run without awaiting the loadData method inside the Action : 2)使用Task.Run而不等待Action内的loadData方法:

await Task.Run(() => { ViewModel.loadData(); });

3) Call my loadData method with: 3)调用我的loadData方法:

await ViewModel.loadData().ConfigureAwait(false);

4) Call the loadData method without awaiting it in my View class and use Task.Run inside my loadData method: 4)调用loadData方法而不在我的View类中等待它,并在我的loadData方法中使用Task.Run:

View: 视图:

private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
    ViewModel.loadData();  
}

ViewModel: 视图模型:

public async void loadData()
{
    await Task.Run(async () => 
    {
        this.Source = await loadStuffFromDatabaseAsync();
    });
}

What are the main differences between these approaces? 这些协议之间的主要区别是什么?

Is one more efficient that the other, and should I pick one in particular? 一个比另一个更高效,我应该特别选择一个吗?

Thanks for your help! 谢谢你的帮助! :) :)

Sergio 塞尔吉奥

You should only use Task.Run if you have CPU-bound or blocking work that you want to move off the UI thread. 如果您Task.Run UI线程移出CPU绑定或阻塞工作,则应该只使用Task.Run That's not the case here, so the direct call (option 3) is the most natural. 情况并非如此,因此直接调用(选项3)是最自然的。

Taking them in turn: 轮流拿走它们:

await Task.Run(async () => { await ViewMode.loadData(); });

This option will execute loadData on a thread pool thread. 此选项将在线程池线程上执行loadData This may not work very well, since loadData is updating the UI (indirectly by setting a VM property). 这可能无法很好地工作,因为loadData正在更新UI(通过设置VM属性间接)。 Even if it does happen to work (ie, some MVVM frameworks can properly handle updates from background threads in some scenarios), it's probably unnecessary since loadData is an asynchronous method. 即使它确实发生了工作(即,某些MVVM框架可以在某些情况下正确处理来自后台线程的更新),但由于loadData是一种异步方法,因此可能没有必要。

Furthermore, it adds async state machine overhead for no reason. 此外,它无缘无故地添加async状态机开销。

await Task.Run(() => { ViewModel.loadData(); });

This option has all the same problems, except it's slightly more efficient since it doesn't have the async state machine overhead. 此选项具有所有相同的问题,除了它稍微更高效,因为它没有async状态机开销。 But it's still updating VM properties on a background thread and using a background thread unnecessarily. 但它仍然在后台线程上更新VM属性并且不必要地使用后台线程。

public async void loadData()

This one's the worst of all. 这是最糟糕的。 It inherits the same problems of the others: updating VM properties on a background thread and using an unnecessary background thread. 它继承了其他问题:在后台线程上更新VM属性并使用不必要的后台线程。 To that it adds the problems of async void . 为此,它增加了async void的问题。 One problem is that NavigationHelper_LoadState cannot catch any exceptions from loadData . 一个问题是NavigationHelper_LoadState无法捕获来自loadData任何异常。 Another problem is that loadData is not easily testable. 另一个问题是loadData不容易测试。

So just use the simple approach and call it directly: 所以只需使用简单的方法并直接调用它:

await ViewModel.loadData().ConfigureAwait(false);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM