C# 计数未出错的任务会导致重新执行每个任务

C# 计数未出错的任务会导致重新执行每个任务,c#,.net,async-await,C#,.net,Async Await,我正在使用异步保存将一组项目保存到数据库中 var tasks = items.Select(item => { var clone = item.MakeCopy(); clone.Id = Guid.NewGuid(); return dbAccess.SaveA

我正在使用异步保存将一组项目保存到数据库中

var tasks = items.Select(item =>
                         {
                             var clone = item.MakeCopy();
                             clone.Id = Guid.NewGuid();

                             return dbAccess.SaveAsync(clone);
                         });

                        await Task.WhenAll(tasks);
我需要验证SaveAsync成功了多少次(如果出现问题,它会抛出异常)。我正在使用IsFaulted标志检查任务:

                        var successCount = tasks.Count(t => !t.IsFaulted);
集合由3个元素组成,因此SaveAsync应该被调用三次,但执行了6次。仔细检查后,我注意到使用c.Count(…)计算未出错的任务会导致每个任务重新运行

我怀疑这与延迟的LINQ执行有关,但我不确定确切原因以及如何解决这个问题


有什么建议说明我为什么要观察这种行为,以及什么是避免这种工件的最佳模式吗?

这是因为您的
Select
查询多次枚举造成的

为了修复它,通过调用
ToList()
方法强制枚举。然后它就会正常工作

var tasks = items.Select(item =>
                     {
                         var clone = item.MakeCopy();
                         clone.Id = Guid.NewGuid();
                         return dbAccess.SaveAsync(clone);
                     })
                 .ToList();
您还可以查看这些更详细的答案:


Linked answers目前没有提及导致这种行为的实际特征,即。Linq
IEnumerable
/
IQueryable
扩展默认为“延迟执行”,这意味着在调用这些扩展时,它们的实际执行不会发生,而是在迭代其他扩展时发生,它们的结果是
IEnumerable
/
IQueryable
。每次重新枚举其结果
IEnumerable
/
IQueryable
时,它们的执行也会再次发生。