Raj*_*mar 5 c# linq performance winforms
我正在使用以下查询
foreach (var callDetailsForNode_ReArrange in callDetailsForNodes_ReArrange)
{
var test = from r1 in dtRowForNode.AsEnumerable()
join r2 in dtFileRowForNode.AsEnumerable()
on r1.Field<int>("Lng_Upload_Id") equals r2.Field<int>("Lng_Upload_Id")
where ((r1.Field<string>("Txt_Called_Number") == callDetailsForNode_ReArrange.caller2.ToString()) || r1.Field<string>("Txt_Calling_Number") == callDetailsForNode_ReArrange.caller2.ToString())
select r2.Field<string>("Txt_File_Name");
var d = test.Distinct();
}
Run Code Online (Sandbox Code Playgroud)
此时此查询立即运行.但正如我补充道
string[] str =d.ToArray();
strFileName = string.Join(",", str);
Run Code Online (Sandbox Code Playgroud)
运行大约需要4-5秒.什么使它添加如此缓慢.ToArray()?
Mar*_*ell 15
此时此查询立即运行.
到目前为止,除了构建表示挂起查询的延迟执行模型之外,它实际上没有做任何事情.在你调用迭代器之前,它不会开始迭代,即在你的情况下通过.MoveNext()foreach.ToArray()
所以:它需要时间,因为它正在做工作.
考虑:
static IEnumerable<int> GetData()
{
Console.WriteLine("a");
yield return 0;
Console.WriteLine("b");
yield return 1;
Console.WriteLine("c");
yield return 2;
Console.WriteLine("d");
}
static void Main()
{
Console.WriteLine("start");
var data = GetData();
Console.WriteLine("got data");
foreach (var item in data)
Console.WriteLine(item);
Console.WriteLine("end");
}
Run Code Online (Sandbox Code Playgroud)
这输出:
start
got data
a
0
b
1
c
2
d
end
Run Code Online (Sandbox Code Playgroud)
需要注意的是如何工作的不一切发生一次-它既是延迟(a说到后got data)和后台(我们没有得到a,... d,0... 2).
相关:这大致是如何Distinct()工作的,来自评论:
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source) {
var seen = new HashSet<T>();
foreach(var item in source) {
if(seen.Add(item)) yield return item;
}
}
Run Code Online (Sandbox Code Playgroud)
...
和一个新的Join操作:
public static string Join(this IEnumerable<string> source, string separator) {
using(var iter = source.GetEnumerator()) {
if(!iter.MoveNext()) return "";
var sb = new StringBuilder(iter.Current);
while(iter.MoveNext())
sb.Append(separator).Append(iter.Current);
return sb.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
并使用:
string s = d.Join(",");
Run Code Online (Sandbox Code Playgroud)
Mat*_*son 12
因为在你迭代它之前查询没有任何作用,这样.ToArray()做.
需要注意的一点是,r2 in dtFileRowForNode.AsEnumerable()当查询开始迭代时,连接的右侧(在您的示例中)将完全枚举,即使只访问结果的第一个元素 - 但不是直到那时.
所以,如果你这样做:
d.First()
该r2 in dtFileRowForNode.AsEnumerable()序列将完全迭代(和在存储器中缓冲的),但是只有第一个元素r1 in dtRowForNode.AsEnumerable()将被评估.
因此,如果连接中的一个序列比另一个序列大得多,则将大序列放在连接的左侧会更有效(以内存方式).连接右侧的整个序列将缓冲在内存中.
(我应该指出,只适用于Linq-to-objects.Linq-to-SQL将在数据库中运行这些查询,因此它处理缓冲.)
| 归档时间: |
|
| 查看次数: |
1546 次 |
| 最近记录: |