C# 替换嵌套的foreach以提高性能

C# 替换嵌套的foreach以提高性能,c#,performance,linq,C#,Performance,Linq,我有以下代码,执行这些代码需要更长的时间。是否有任何替代方案,我可以用LINQ或任何其他方式来替换下面的代码以提高性能 var usedLists = new HashSet<long>(); foreach (var test in Tests) { var requiredLists = this.GetLists(test.test, selectedTag); foreach (var List in requiredLists) {

我有以下代码,执行这些代码需要更长的时间。是否有任何替代方案,我可以用LINQ或任何其他方式来替换下面的代码以提高性能

var usedLists = new HashSet<long>();

foreach (var test in Tests)
{
    var requiredLists = this.GetLists(test.test, selectedTag);

    foreach (var List in requiredLists)
    {   
        if (!usedLists.Contains(List.Id))
        {
            usedLists.Add(List.Id);
            var toRecipients = List.RecepientsTo;
            var ccRecipients = List.RecipientsCC;
            var bccRecipients = List.RecipientsBCC;
            var replyTo = new List<string>() { List.ReplyTo };
            var mailMode = isPreviewMode ? MailMode.Display : MailMode.Drafts;
            OutlookModel.Instance.CreateEmail(toRecipients, ccRecipients, bccRecipients, this.Draft, mailMode, replyTo);
        }
    }
}
var usedLists=newhashset();
foreach(测试中的var测试)
{
var requiredLists=this.GetLists(test.test,selectedTag);
foreach(所需列表中的var列表)
{   
如果(!usedLists.Contains(List.Id))
{
usedLists.Add(List.Id);
var toRecipients=List.RecepientsTo;
var ccRecipients=List.RecipientsCC;
var bccreciients=List.RecipientsBCC;
var replyTo=new List(){List.replyTo};
var mailMode=isPreviewMode?mailMode.Display:mailMode.Drafts;
OutlookModel.Instance.CreateEmail(toRecipients、ccRecipients、BCRecipients、this.Draft、mailMode、replyTo);
}
}
}

它可能可以用或类似的东西来完成。 一个非常粗略的轮廓是将createemail参数包装到一个单独的类中,然后在循环继续处理列表的同时异步启动后台任务

编辑 这可能也有用。这是假设CreateEmail函数是一个占用所有时间的函数。如果这条环线一直在走,那么走这条路线就没有意义了

编辑 从算法复杂性来看,GetList()调用在O(n)时间内运行,而CreateEmail()调用在O(n^2)时间内运行,因此,在所有其他条件相同的情况下,包含CreateEmail()调用的代码块将是首先进行优化的更好候选对象。

  • 每个foreach循环都会创建一个枚举器对象,因此使用常规for循环可能会稍微加快速度,但这可能只是一个很小的改进
  • 正如stormenet所说,CreateEmail功能可能是瓶颈。您可能希望使其异步

假设与
CreateEmail
调用相比,
GetList
的结果足够大/慢,跳过contains-add-hashset比较将加快速度。尝试调用Distinct([您的ListComparer])或GroupBy():

您也可以尝试加快速度,但我认为您可能会在CreateEmail调用中遇到问题,因为它可能是一个COM对象,所以多线程将是一个麻烦。如果GetList的速度足够慢,值得多线程开销,那么在创建
requiredList
时,您可以在第一次调用中尝试使用它

你实际上是做什么的? 看着

foreach (var test in Tests)
{
    var requiredLists = this.GetLists(test.test, selectedTag);
    foreach (var List in requiredLists)
    {   
        if (!usedLists.Contains(List.Id))
在我看来,您试图获得唯一的“列表”(对于所有这些“变量”,我无法说出实际的类型)。所以你实际上可以用一个新函数(由你编写)来代替它

最后打电话

this.Sendmails(uniqueLists);
它将遍历该列表并发送邮件

这是否能加快代码的速度,严重取决于底层的getlist/GetUniqueLists函数


但是在任何情况下,它都会使您的代码有很大的进步:它变得可读且可测试。

我怀疑您使用linq是否能更快地获得它,我怀疑
CreateEmail
函数会占用所有的时间。分析代码,看看真正的瓶颈在哪里。不,这基本上是最好的。你的
这个.getlist
方法怎么样?除了这两种方法之外,在这段代码中没有什么可能消耗那么多。或者,如果不符合您的需要(因为您总是发送相同的草稿),您可能会立即发送分组邮件。不清楚有多少测试以及它们来自何处。如果每个GetLists调用都是对DB的查询,并且有很多列表,那么可以通过在进入循环之前一次查询DB来加快查询速度。
var uniqueLists = this.GetUniqueLists(Tests, selectedTag);
this.Sendmails(uniqueLists);