本文介绍了在大型数据集上执行LINQ表达式时如何报告进度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我需要使用LINQ生成相当大的数据集,并且可能需要一段时间(例如几秒钟),并且我需要(希望)生成有关使用情况的反馈信息,请问是否已经完成了%'age /首选方式?

If I need generate a fairly large dataset using LINQ and it may take a while (say a few seconds) and I need to (would like to) generate feedback to the use as to %'age done, is there an easy/ preferred way to do this?

例如,假设我有1000辆汽车的清单A和100​​0辆卡车的清单B,我想选择所有可能的有序(汽车,卡车)对,其中car.color == truck.color链接到此:

Example, say I have list A with 1000 cars and list B with 1000 trucks and I want to select all possible ordered (car, truck) pairs where car.color == truck.color link this:

var pairs = from car in A 
            from truck in B 
            where car.color==truck.color 
            select new {car, truck};

现在在某些时候,它将被评估为一组嵌套的foreach循环.我希望能够报告完成的%'age年龄,并且理想情况下可以更新进度条或其他内容.

Now at some point this will be evaluated as a set of nested foreach loops. I would like to be able to report %'age complete as it interates and ideally update a progressbar or something.

查询后,我将结果存储在一个成员变量中,像这样的列表(这将强制执行查询):

Just after my query, I store the result in a member variable as a list like this (which forces the query to execute):

mPairs = pairs.ToList();

之所以这样做是因为我在后台工作线程中执行此操作,因为我不希望UI线程冻结,因为它会按需评估UI线程上的LINQ表达式(这在Silverlight BTW中).因此,为什么我要报告进度. UX基本上是这样的:

I do this because I am executing this in a background worker thread as I do not want the UI thread to freeze up as it evaluates the LINQ expression on demand on the UI thread (this is in Silverlight BTW). Hence why I would like to report progress. The UX is basically this:

  1. 用户将项目拖到工作区上
  2. 然后,引擎在后台线程中启动,以确定与工作空间中所有其他项目的(许多)连接可能性.
  3. 引擎正在计算UI时,不允许新连接,并报告进度以指示新项目何时可连接"到其他项目(尚未使用的所有可能的连接路径均已通过LINQ确定).
  4. 当引擎完成计算(查询)时,该项目可在UI中连接,并且可能的连接路径存储在本地变量中以备将来使用(例如,当用户单击以连接该项目时,所有可能的路径将根据添加时的计算结果突出显示)

(删除项目时必须执行类似的过程)

(a similar process must happen on deletion of an item)

推荐答案

我使用的效果很好的是DataContext的适配器,该适配器返回了它产生的项数的计数.

Something I used that worked well was an adapter for the DataContext that returned a count of the number of items it's yielded.

public class ProgressArgs : EventArgs
{
    public ProgressArgs(int count)
    {
        this.Count = count;
    }

    public int Count { get; private set; }
}

public class ProgressContext<T> : IEnumerable<T>
{
    private IEnumerable<T> source;

    public ProgressContext(IEnumerable<T> source)
    {
        this.source = source;
    }

    public event EventHandler<ProgressArgs> UpdateProgress;

    protected virtual void OnUpdateProgress(int count)
    {
        EventHandler<ProgressArgs> handler = this.UpdateProgress;
        if (handler != null)
            handler(this, new ProgressArgs(count));
    }

    public IEnumerator<T> GetEnumerator()
    {
        int count = 0;
        foreach (var item in source)
        {
            // The yield holds execution until the next iteration,
            // so trigger the update event first.
            OnUpdateProgress(++count);
            yield return item;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

用法

var context = new ProgressContext(
    from car in A 
    from truck in B 
    select new {car, truck};
);
context.UpdateProgress += (sender, e) =>
{
    // Do your update here
};

var query = from item in context
            where item.car.color==item.truck.color;

// This will trigger the updates
query.ToArray();

唯一的问题是,除非您知道总数,否则您无法轻易得出百分比.要进行总计数通常需要处理整个列表,这可能会很昂贵.如果您确实知道总数,那么可以在UpdateProgress事件处理程序中计算一个百分比.

The only issue is you can't easily do a percentage unless you know the total count. To do a total count often requires processing the entire list, which can be costly. If you do know the total count beforehand then you can work out a percentage in the UpdateProgress event handler.

这篇关于在大型数据集上执行LINQ表达式时如何报告进度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 22:21