2013-05-07 44 views
2

我有一個Busy屬性,在異步調用之前設置爲true,然後在完成時設置爲false。現在我有2個異步調用,我該如何處理這個邏輯?我是否需要鎖定變量或其他需要注意的並行問題?多個異步調用的繁忙指示器

private bool _busy; 

public bool Busy 
{ 
    get { return _busy; } 
    set 
    { 
     bool changed = value != _busy; 
     _busy = value; 
     if (changed) RaisePropertyChanged("Busy"); 
    } 
} 

private void loadUser(int userId) 
{ 
     Busy = true; 
     api.GetUser(userId, CancellationToken.None).ContinueWith(t => 
             Deployment.Current.Dispatcher.BeginInvoke(() => 
             { 
              Busy = false; 
             })); 

} 

private void loadOtherData(int dataId) 
{ 
     Busy = true; 
     api.GetData(dataId, CancellationToken.None).ContinueWith(t => 
             Deployment.Current.Dispatcher.BeginInvoke(() => 
             { 
              Busy = false; 
             })); 

} 

我知道這個邏輯有缺陷,因爲Busy屬性在完成執行的第一個方法上設置爲false。我有一個想法是使用2個字段; isUserLoadingisOtherDataLoading,並確保在將Busy設置爲false之前兩者均爲false。

我想知道是否有更好的方法來實現這一點。

+0

我一直在使用一個數字計數器(其中您的異步調用將遞增/遞減)與像布爾忙屬性{獲得{ return _count!= 0; }}。我很好奇看到別人推薦。 – mztan 2013-05-07 00:34:52

回答

2

如果你有兩個布爾值,_isUserLoading_isOtherDataLoading,您在load方法更新,那麼你可以改變Busy這樣:

public bool busy 
{ 
    get 
    { 
     return _isUserLoading || _isOtherDataLoading; 
    } 
} 

另一個版本包括調用RaisePropertyChanged可以工作像這樣:

public bool busy 
{ 
    get 
    { 
     return _isUserLoading || _isOtherDataLoading; 
    } 
} 

public bool IsUserLoading 
{ 
    get 
    { 
     return _isUserLoading; 
    } 
    set 
    { 
     bool busy = Busy; 
     _isUserLoading = value; 
     if (busy != Busy) RaisePropertyChanged("Busy"); 
    } 
} 

當然還有一個類似的屬性爲IsOtherDataLoading

+0

我必須擔心Busy屬性上的鎖嗎? – 2013-05-07 00:53:11

+0

我如何處理notifproroperty?我編輯了我的問題 – 2013-05-07 00:55:00

+0

查看我的編輯,上面有一種方法可以包含RaisePropertyChanged調用 – joshuahealy 2013-05-07 02:05:44

0

理想情況下,您想從API中暴露一個可觀察的屬性/事件,指出它何時處於繁忙狀態。假設你不能做任何修改,我會建議你採用更通用的方法。像

class CountedContext { 
    int workersCount = 0; 
    Action<bool> notifier; 

    public CountedContext(Action<bool> notifier) { this.notifier = notifier; } 

    public Task<TResult> Execte<TResult>(Func<Task<TResult>> func) 
    { 
     lock(worksersCount) 
     { 
      workersCount++; 

      if (workdersCount == 1) 
       notifier(true); 
     } 

     var result = func(); 

     result.ContinueWith(_ => 
     { 
      lock (worksersCount) 
      { 
       workersCount--; 

       if (worksersCount == 0){ 
        notifier(false); 
       } 
      } 
     }); 

     return result; 
    } 
} 

東西在你的主類,你可以使用:

// constructor: 
countedContext = new CountedContext(state => 
{ 
    ...BeginInvoke(() => 
    { 
     Busy = state; 
    }); 
}); 

... 

// loadData 
countedContext.Execute(() => api.GetData()); 
+0

如果可以修改API,還可以顯示版本嗎? – 2013-05-07 04:21:13

+0

您可以使用類似的技術,但更多地嵌入在API中 – Polity 2013-05-07 11:59:25