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假的。

我想知道是否有更好的方法来实现这一点。

4

2 回答 2

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.

于 2013-05-07T00:34:20.217 回答
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());
于 2013-05-07T02:30:28.190 回答