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 つのフィールドを使用することです。isUserLoadingそしてisOtherDataLoading、false に設定する前に、両方が false であることを確認Busyします。

これを達成するためのより良い方法があるかどうか知りたいです。

4

2 に答える 2

2

ロード メソッドで更新する2 つのブール値_isUserLoadingとがある場合は、次のように変更できます。_isOtherDataLoadingBusy

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 に答える