簡體   English   中英

如何實現異步INotifyPropertyChanged

[英]How to implement async INotifyPropertyChanged

我有一個類,其屬性綁定到我的視圖。 為了使我的視圖保持最新,我實現了INotifyPropertyChanged並在每次某些屬性更改時引發事件。

現在我得到了一些重要的函數來凍結我的應用程序 我想把它們放到后台任務中。

第一:這是我目前的做法

(例如點擊按鈕)

private async void HeavyFunc()
{
    foreach (var stuff)
    {
        count += await Task.Run(() => stuff.Fetch());
    }

    if (count == 0)
        //...
}

東西類

public async Task<int> Fetch()
{
    //network stuff

    RaisePropertyChanged("MyProperty");
}

public async void RaisePropertyChanged(string pChangedProperty)
{
    await Application.Current.Dispatcher.BeginInvoke(
        System.Windows.Threading.DispatcherPriority.Normal,
        new ThreadStart(() =>
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pChangedProperty);
        }
    );
}

上面的代碼給出了一個異常(“DependencySource”必須在同一個線程中創建,如“DependencyObject”)。

AFAIK,你通常需要創建一個新線程並運行它(等待它)。 'goit Task.Run(...);'應該做這個工作。

由於PropertyChanged事件直接影響UI,因此在UI線程中調用它似乎是一個很好的決定。 這就是我調用Dispatcher.BeginInvoke的原因。

我不明白:上面的例外是由不同的線程負責數據引起的。 但我明確地在我的UI線程上調用該事件,該對象也應該由UI線程創建。 那么為什么我會得到例外?

我的主要問題是:如何實現INotifyPropertyChanged接口的事件通常是為了避免或處理上面的大多數異步編程問題? 構建函數時應該考慮什么?

現在我得到了一些重要的函數來凍結我的應用程序

如果你真的在做異步“網絡東西”,那么它不應該凍結應用程序。

我的主要問題是:如何實現INotifyPropertyChanged接口的事件通常是為了避免或處理上面的大多數異步編程問題?

我更喜歡的方法是在提升代碼時處理這個問題。 相反,構建其余代碼以使其尊重UI層。

換句話說,將“服務”(或“業務邏輯”)代碼從“UI”代碼中划分出來,使其工作方式如下:

// In StuffService class:
public async Task<Result> FetchAsync()
{
  //network stuff
  return result;
}

// In StuffViewModel class:
public async void ButtonClicked()
{
  foreach (var stuff)
  {
    var result = await Task.Run(() => _stuffService.FetchAsync());
    MyProperty = result.MyProperty;
    count += result.Count;
  }

  if (count == 0)
    //...
}

public Property MyProperty
{
  get { return _myProperty; }
  set
  {
    _myProperty = value;
    RaisePropertyChanged();
  }
}
private void RaisePropertyChanged([CallerMemberName] string pChangedProperty = null)
{
  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pChangedProperty));
}

這樣,就沒有手動跳線,所有屬性都有標准的ViewModel實現,代碼更簡單,更易於維護等。

我確實離開了對Task.Run的調用,盡管如果您的網絡調用是真正的異步,這應該是多余的。

暫無
暫無

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

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