0

私は、ユーザーが入力したデータに基づいて、おそらく長時間実行されるループと計算を行う必要がある Win 8 アプリを開発しています。この計算は、結果をリアルタイムで更新するために頻繁に実行されます。

計算は電卓クラスによって行われます。サンプルコードを使用してアイデアを提供します

public class ResultCalculator
{
    List<Data> Input1 = new List<Data>();
    IQueryable<int> Input2;
    IQueryable<Data2> Input3;

    public ResultCalculator(List<int> items1, List<Data2> items2)
    {
        items1.Sort((x,y) => y.CompareTo(x));
        Input2 = items1.AsQueryable();
        Input3 = items2.AsQueryable().OrderByDescending(w => w.LValue);
    }

    public void CalculateLValues()
    {
        foreach (var v in Input3)
        {
            for (int i = 1; i <= v.Quantity; i++)
            {
                if (Input1.Count > 0)
                {
                    Data existing = FindExisting(v.LValue, 4);

                    if (existing != null)
                    {
                        existing.Add(v.LValue);
                    }
                    else
                    {
                        FindNew(v.LValue);
                    }
                }
                else
                {
                    FindNew(v.LValue);
                }
            }
        }

        OptimisePass1(); 
    }

    public void FindNew(int LValue)
    {
        int options = FindNewItem(LValue, 0);

        if (options != 0)
        {
            Data newdata = new Data(options);
            newdata.Add(LValue);
            Input1.Add(newdata);
        }
    }

    public void OptimisePass1()
    {
        foreach (var w in Input1)
        {
            var ShorterLValues = from sl in Input2 where sl < w.LValue orderby sl select sl;

            foreach (var sl in ShorterLValues)
            {
                if (sl > w.LValue - w.Remaining)
                {
                    w.LValue = sl;
                    w.CalculateRemaining();
                }
            }

    // MORE CALCULATION TO DO IN ANOTHER LOOP
        }
    }

    public Data FindExisting(int LValueRequired, int additionalvalue)
    {
        Input1.OrderBy(w => w.LValue);

        foreach (var sl in Input1.Where(i => i.Remaining > 0).OrderBy(i => i.Remaining))
        {
            if (sl.Remaining >= LValueRequired + additionalvalue)
            {
                return sl;
            }
        }
        return null;
    }

    public int FindNewItem(int LValueRequired)
    {
        foreach (var sl in Input2)
        {
            if (sl >= LValueRequired + 4)
            {
                return sl;
            }
        }
        return 0;
    }

}

このクラスは、以下のように ViewModel から使用されます...

public async Task UpdateCalculationAsync()
{
    var data1 = new List<int>(sInput);
    var reqlist = new List<Data2>(sInput2);

    var lc = new ResultCalculator(data1, data2);
    NL.Clear();

    await Task.Run(() => lc.CalculateLValues());

    foreach (var i in lc.Data1)
    {
        NL.Add(i);
    }
}

リストに多くのアイテムがある場合、非同期を使用しないと、実行時にUIが停止しました。そこで、「await Task.Run(() => lc.CalculateLValues())」を追加して、非同期で実行するようにしました。私は非同期の基本的な理解を持っていますが、クラスを非同期で適切に実行する方法を本当に理解していません。このアプローチは正しいですか?

私が行ったことは、計算をバックグラウンド スレッドに渡すことだと思います。確かに、UI はレスポンシブのままになり、計算の実行中に使用できます。結果が計算されると、ビューモデルが結果を取得し、UI が更新されます。私が本当に望んでいるのは、ResultCalculator クラスに Task を返すメソッドがあり、それを待機できるようにすることです。しかし、私はそのためにリファクタリングする方法に本当に苦労しています。これが機能し、有効なアプローチである場合、必要があるかどうかさえわかりません。しかし、それが非同期パターンの適切な使用であると 100% 確信しているわけではなく、改善できるかどうかを確認したかったのですか?

4

1 に答える 1

0

次のようなことを提案します。

// user will do some action on the UI to trigger the compute
public async Task Button1_Click(..)
{
    await this.ViewModel.RecalculateAsync();
}

class ViewModel
{
    public async Task RecalculateAsync()
    {
        var data1 = new List<int>(sInput);
        var reqlist = new List<Data2>(sInput2);
        var lc = new ResultCalculator(data1, data2);
        await Task.Run(() => lc.CalculateLValues());
        // I am not sure that is NL - if it is items like property on viewmodel that is bound to ListView like control in xaml - that should be fine.
        // otherwise, add code here to add the list of result items to an observable collection
        // expose this collection as Items property on viewmodel and bind in xaml to ListView.ItemsSource
    }
}
于 2013-04-07T11:27:53.783 に答える