从 outlook 获取电子邮件时 VSTO C# 中 For 循环的性能问题
Performance issue with For loop in VSTO C# while getting emails from outlook
我在循环浏览 Outlook 收件箱文件夹中的电子邮件时遇到问题(在 Outlook 中添加 C# VSTO)。
我正在使用 foreach 循环,但它消耗了大量内存,然后导致异常:system/memory 资源不足。
所以,我现在正在使用 for 循环,它不会导致该错误,但对于其中一个文件夹来说它真的很慢,每秒读取不到 5-8 封电子邮件。此文件夹包含超过 100,000 封电子邮件。对于所有其他文件夹,速度在 30-35 封电子邮件之间。
密码是:
Static void IterateMessages(Outlook.Folder folder){
int tempCount = folder.Items.Count;
if (folder.Items != null)
{
Object item;
for (int k = 1; k <= tempCount; k++)
{
item = folder.Items[k];
if (item is Outlook.MailItem)
{
emailCount++;
try
{
SaveAttachment(item);
}
catch (Exception e)
{
Debug.WriteLine("An error occurred Iterate Message: '{0}'", e);
}
}
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(item);
item = null;
}
tempCount = 0;
}
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(folder);
}
如果有人能帮助解决这个问题就太好了。使用 foreach 循环时,速度约为。每秒 40-45 封电子邮件。此外,此方法是从另一个遍历文件夹的 for 循环调用的,在此先感谢
首先,遍历文件夹中的所有项目不是一个好主意。你真的需要这样做吗?
您一直在循环中检索 Items 集合 (folder.Items[k]
)。进入循环前缓存Items
:
Items items = folder.Items;
for (int k = 1; k <= items.Count; k++)
{
object item = items[k];
...
}
Marshal.ReleaseComObject(items);
您正在泄漏引用(它们稍后将由 GC 释放),但是由于您使用的是 FinalReleaseComObject...
object item = items[k];
MailItem mailItem = item as MailItem;
if (mailItem != null)
{
...
Marshal.ReleaseComObject(mailItem);
}
Marshal.ReleaseComObject(item);
正确释放底层 COM 对象不足以实现您的目标。您无需遍历文件夹中的所有项目,而是需要使用 Items
class 的 Find
/FindNext
或 Restrict
方法来查找带有附件的项目和只有这样你才能遍历所有只有附件的项目。查询可以使用 SQL 表示法 (VBA):
query ="@SQL=" & chr(34) & "urn:schemas:httpmail:hasattachment" & chr(34) & "=1"
在以下文章中阅读有关这些方法的更多信息:
- How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
- How To: Use Restrict method to retrieve Outlook mail items from a folder
此外,您可能会发现应用程序 class 的 AdvancedSearch
方法很有用。在 Outlook 中使用 AdvancedSearch
方法的主要好处是:
- 搜索在另一个线程中执行。您不需要手动 运行 另一个线程,因为
AdvancedSearch
方法 运行 它会自动在后台运行。
- 可以在任何位置(即超出某个文件夹的范围)搜索任何项目类型:邮件、约会、日历、便笺等。
Restrict
和 Find
/FindNext
方法可以应用于特定的 Items
集合(参见 [=23= 的 Items
属性 ] class 在 Outlook 中)。
- 完全支持 DASL 查询(自定义属性也可用于搜索)。您可以在 MSDN 的 Filtering 文章中阅读更多相关信息。为了提高搜索性能,如果为商店启用了即时搜索,则可以使用即时搜索关键字(参见
Store
class 的 IsInstantSearchEnabled
属性)。
- 您可以随时使用
Search
class 的 Stop
方法停止搜索过程。
有关详细信息,请参阅 Advanced search in Outlook programmatically: C#, VB.NET。
我在循环浏览 Outlook 收件箱文件夹中的电子邮件时遇到问题(在 Outlook 中添加 C# VSTO)。 我正在使用 foreach 循环,但它消耗了大量内存,然后导致异常:system/memory 资源不足。 所以,我现在正在使用 for 循环,它不会导致该错误,但对于其中一个文件夹来说它真的很慢,每秒读取不到 5-8 封电子邮件。此文件夹包含超过 100,000 封电子邮件。对于所有其他文件夹,速度在 30-35 封电子邮件之间。
密码是:
Static void IterateMessages(Outlook.Folder folder){
int tempCount = folder.Items.Count;
if (folder.Items != null)
{
Object item;
for (int k = 1; k <= tempCount; k++)
{
item = folder.Items[k];
if (item is Outlook.MailItem)
{
emailCount++;
try
{
SaveAttachment(item);
}
catch (Exception e)
{
Debug.WriteLine("An error occurred Iterate Message: '{0}'", e);
}
}
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(item);
item = null;
}
tempCount = 0;
}
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(folder);
}
如果有人能帮助解决这个问题就太好了。使用 foreach 循环时,速度约为。每秒 40-45 封电子邮件。此外,此方法是从另一个遍历文件夹的 for 循环调用的,在此先感谢
首先,遍历文件夹中的所有项目不是一个好主意。你真的需要这样做吗?
您一直在循环中检索 Items 集合 (folder.Items[k]
)。进入循环前缓存Items
:
Items items = folder.Items;
for (int k = 1; k <= items.Count; k++)
{
object item = items[k];
...
}
Marshal.ReleaseComObject(items);
您正在泄漏引用(它们稍后将由 GC 释放),但是由于您使用的是 FinalReleaseComObject...
object item = items[k];
MailItem mailItem = item as MailItem;
if (mailItem != null)
{
...
Marshal.ReleaseComObject(mailItem);
}
Marshal.ReleaseComObject(item);
正确释放底层 COM 对象不足以实现您的目标。您无需遍历文件夹中的所有项目,而是需要使用 Items
class 的 Find
/FindNext
或 Restrict
方法来查找带有附件的项目和只有这样你才能遍历所有只有附件的项目。查询可以使用 SQL 表示法 (VBA):
query ="@SQL=" & chr(34) & "urn:schemas:httpmail:hasattachment" & chr(34) & "=1"
在以下文章中阅读有关这些方法的更多信息:
- How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
- How To: Use Restrict method to retrieve Outlook mail items from a folder
此外,您可能会发现应用程序 class 的 AdvancedSearch
方法很有用。在 Outlook 中使用 AdvancedSearch
方法的主要好处是:
- 搜索在另一个线程中执行。您不需要手动 运行 另一个线程,因为
AdvancedSearch
方法 运行 它会自动在后台运行。 - 可以在任何位置(即超出某个文件夹的范围)搜索任何项目类型:邮件、约会、日历、便笺等。
Restrict
和Find
/FindNext
方法可以应用于特定的Items
集合(参见 [=23= 的Items
属性 ] class 在 Outlook 中)。 - 完全支持 DASL 查询(自定义属性也可用于搜索)。您可以在 MSDN 的 Filtering 文章中阅读更多相关信息。为了提高搜索性能,如果为商店启用了即时搜索,则可以使用即时搜索关键字(参见
Store
class 的IsInstantSearchEnabled
属性)。 - 您可以随时使用
Search
class 的Stop
方法停止搜索过程。
有关详细信息,请参阅 Advanced search in Outlook programmatically: C#, VB.NET。