我有一个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。我的想法是使用另外两个字段;在将isUserLoading
设置为false之前,isOtherDataLoading
和Busy
并确保两者均为假。
我想知道是否有更好的方法来实现这一目标。
答案 0 :(得分:2)
如果你有两个布尔值_isUserLoading
和_isOtherDataLoading
,你在加载方法中更新,那么你可以将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
的类似属性。
答案 1 :(得分: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());