2014-05-20 44 views
3

我有以下代码需要较长的时间来执行。有什么替代方案可以用LINQ或其他任何方式替代下面的代码来提高性能?替换嵌套的foreach以提高性能

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); 
     } 
    } 
} 
+11

我怀疑你会用linq更快地获得它,我怀疑'CreateEmail'函数总是占用所有的时间。剖析你的代码,看看真正的瓶颈在哪里。 http://stackoverflow.com/questions/3927/what-are-some-good-net-profilers – Stormenet

+0

不,那基本上是最好的。 – TheGeekZn

+0

你的'this.GetLists'方法呢?除了这两种方法之外,没有什么东西可能会在代码中消耗太多。或者,如果这不符合你需要做的事情(因为你总是发送相同的草稿),你可能会立即发送一个分组邮件 – mmg666

回答

1

你实际上做了什么? 看着

foreach (var test in Tests) 
{ 
    var requiredLists = this.GetLists(test.test, selectedTag); 
    foreach (var List in requiredLists) 
    { 
     if (!usedLists.Contains(List.Id)) 

在我看来,你尝试获得独特的“清单” S(与所有这些“变种”我不能告诉具体型号)。所以,你原本可以替换成一个新的函数(被你写的),做

var uniqueLists = this.GetUniqueLists(Tests, selectedTag); 

最后调用

this.Sendmails(uniqueLists); 

这将遍历直通该名单并发送邮件。

如果这可以加快代码速度,严重依赖底层的GetLists/GetUniqueLists函数。

但是无论如何,它会让你的代码有一个很大的进步:它变得可读性和可测试性。

1

具有相似的BackgroundWorker class或做事情也许是不能。 一个非常粗略的概述是将创建电子邮件参数封装到单独的类中,然后在循环继续处理列表时异步启动后台任务。

编辑 Task class也可能有用。这是假定CreateEmail函数是一直占用的函数。如果这是一直在循环的循环,那么通过这条路线是没有意义的。

编辑 望着算法的复杂性,GetLists()在O(n)的时间调用运行,但CreateEmail()调用为O运行(N^2)时间,所以 - 所有其他的事情都是平等 - 包含CreateEmail()调用的代码块将成为首选优化的更好选择。

0
  • 每个foreach循环都会创建一个Enumerator对象,所以使用常规的for-loop可能会加快它的速度,但这可能是一个很小的改进。
  • 就像stormenet所说,CreateEmail函数可能是瓶颈。您可能想要使该异步。
1

GetList假设结果是大/相较于CreateEmail调用足够慢,跳过你的包含加HashSet的比较将加快速度。尝试调用鲜明([你ListComparer])或的GroupBy():

var requiredLists = 
    Tests.SelectMany(test => this.GetLists(test.test, selectedTag)) 
     .Distinct([Your ListComparer]); 
// or 
var requiredLists = 
    Tests.SelectMany(test => this.GetLists(test.test, selectedTag)) 
     .GroupBy(x => x.Id).SelectMany(x => x.First()); 

foreach (var List in requiredLists) 
{ 
    // (...) 
    OutlookModel.Instance.CreateEmail(toRecipients, ccRecipients, bccRecipients, this.Draft, mailMode, replyTo); 
} 

您也可以尝试PLINQ加快的东西,但我认为你可能会遇到与CreateEmail通话的麻烦,因为它可能是一个COM对象,所以多线程将是一个麻烦。如果GetList速度慢到值多线程开销,那么在创建requiredLists时,可以在第一次调用时尝试使用它。