我有一個Windows Phone手機客戶端與皮膚切換按鈕,它充當「最喜歡的」按鈕。然後,checked屬性將雙向綁定到ViewModel(標準MVVM模式)。使用信號量的異步切換按鈕,以避免服務負荷
<ToggleButton IsChecked="{Binding DataContext.IsFavouriteUser, ElementName=PageRoot, Mode=TwoWay}">
當綁定的布爾值發生變化時,我想啓動一個到服務的異步網絡調用。
public bool IsFavouriteUser
{
get { return _isFavouriteUser; }
set
{
if (SetProperty(ref _isFavouriteUser, value))
{
// Dispatches the state change to a RESTful service call
// in a background thread.
SetFavouriteState();
}
}
}
如果用戶按下按鈕多次,那麼很多添加/刪除異步服務電話可以作出 - 可以想像,這些需要2秒做網絡往返和業務處理。
在過去,我已經使用類似:
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
// I would probably dispatch this call to a background thread in the real client
public async Task<bool> SetFavouriteState()
{
try
{
await _semaphore.WaitAsync();
bool result;
if (IsFavouriteUser)
{
result = await ServiceClient.AddAsync(x);
}
else
{
result = await ServiceClient.RemoveAsync(x);
}
return result;
}
catch
{
// I wouldn't use an empty catch in production code
return false;
}
finally
{
_semaphore.Release();
}
}
然而,這可能無休止地排隊用戶輸入;而服務僅對最新的用戶事件感興趣 - 開啓或關閉 - UI應該對用戶輸入保持響應。
- 如果用戶重複點擊按鈕,確保客戶端不發送「添加/刪除/添加/刪除」的最佳方法是什麼?即我想忽略中間兩個事件,只發送「添加,等待響應完成,刪除」。
- 有沒有更好的方式來以異步的方式綁定到這個布爾屬性?
- 什麼是鎖定我的模型的最佳方式,以便在這種情況下只有一個請求在任何時間點都在進行?
- 什麼是最好的方式告知用戶,當我們等待電話發生(也許失敗)時發生了什麼?