我有以下代码需要更长时间才能执行。有没有替代方法,我可以使用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);
}
}
}
答案 0 :(得分:1)
可以使用BackgroundWorker class或类似的东西来完成。 一个非常粗略的大纲是将创建电子邮件参数包装到一个单独的类中,然后在循环继续处理列表时异步启动后台任务。
修改强> Task class也可能有用。这假设CreateEmail函数是一直占用的函数。如果这是一直在进行的循环,那么走这条路是没有意义的。
修改强> 查看算法的复杂性,GetLists()调用在O(n)时间运行,但CreateEmail()调用在O(n ^ 2)时间运行,因此 - 所有其他条件相同 - 包含CreateEmail的代码块( )呼叫将是优先考虑的更好的候选者。
答案 1 :(得分:1)
假设GetList
的结果与CreateEmail
调用相比足够大/慢,跳过contains-add hashset比较会加快速度。尝试调用Distinct([Your 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
时在第一次调用中对其进行试验。
答案 2 :(得分:1)
你到底做了什么? 看着
foreach (var test in Tests)
{
var requiredLists = this.GetLists(test.test, selectedTag);
foreach (var List in requiredLists)
{
if (!usedLists.Contains(List.Id))
在我看来,你试图获得唯一的“列表”(所有那些“var”我无法分辨实际类型)。所以你实际上可以用一个新函数替换它(由你编写)并执行
var uniqueLists = this.GetUniqueLists(Tests, selectedTag);
最后致电
this.Sendmails(uniqueLists);
将通过该列表进行迭代并发送邮件。
如果这样可以加速代码,则严重依赖于底层的GetLists / GetUniqueLists函数。
但无论如何,它会使你的代码取得很大的进步:它变得可读和可测试。
答案 3 :(得分:0)