簡體   English   中英

從 WPF 視圖模型中的屬性設置器調用異步方法是錯誤的嗎?

[英]Is wrong to invoke an async method from property setter in WPF view model?

當屬性更改其值時,我想調用從 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 上的異步命令,或者為 SelectionChanged 設置一個同步處理程序,它直接調用視圖模型上的更新方法會更好嗎?

從非異步 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

您可能還想研究一個功能性 MVVM 框架,例如通過將屬性轉換為您可以訂閱的可觀察值流來處理這種情況的ReactiveUIhttps : //reactiveui.net/docs/getting-started/

這不是已經說過的“最干凈”的方式,但你可以放棄它。 首先它沒有害處,除非您在快速分配背后隱藏了一個意想不到的漫長而昂貴的操作。

MSDN 說

異步方法也可以有一個 void 返回類型。 此返回類型主要用於定義需要 void 返回類型的事件處理程序。 異步事件處理程序通常作為異步程序的起點。

無法等待具有 void 返回類型的異步方法,並且返回 void 的方法的調用者無法捕獲該方法拋出的任何異常。

一個簡單的解決方案是監聽 PropertyChanged 事件。 這更像是逃避二傳手的解決方法。 更好的方法是通過向 ViewModel 添加異步執行來異步實現ICommand接口,從而使您的 ViewModel 公開更新命令。 然后,無論何時屬性更改,您都可以從您的視圖中調用此 AsyncCommand。 您還可以將新值作為命令參數傳遞給 ViewModel。

當屬性發生變化時自動調用更新本身通常是一個壞主意。
通常一個按鈕和一個命令是一個更好的計划。 您也可以從 UI 調用命令,而不是使用該 setter。 這樣做會相對簡單。

至少,您需要一個不同的線程來以這種方式調用某些 Web 服務。
一個火和忘記線程不會完全是可怕的。
只要你不在乎忘記之后會發生什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM