问题描述
如果我需要使用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和1000辆卡车的清单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:
- 用户将项目拖到工作区上
- 然后,引擎在后台线程中启动,以确定与工作空间中所有其他项目的(许多)连接可能性.
- 引擎正在计算UI时,不允许新连接,并报告进度以指示新项目何时可连接"到其他项目(尚未使用的所有可能的连接路径均已通过LINQ确定).
- 当引擎完成计算(查询)时,该项目可在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表达式时如何报告进度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!