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 回答