#c# #outlook #vsto
Вопрос:
У меня возникли проблемы с циклическим просмотром электронных писем в папках входящих сообщений Outlook (C# VSTO добавить в Outlook). Я использовал цикл foreach, но он потребляет много памяти, а затем вызывает исключение: не хватает ресурсов системы/памяти. Итак, сейчас я использую цикл 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, который перебирает папки, заранее спасибо
Ответ №1:
Во-первых, перебирать все элементы в папке не очень хорошая идея. Тебе действительно нужно это делать?
Вы продолжаете извлекать коллекцию элементов в цикле ( 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);
Комментарии:
1. Привет, Дмитрий, Спасибо за ответ, я хочу просмотреть все элементы в папке, потому что я хочу получить вложения из всех писем, я открыт для того, чтобы попробовать другой способ, если есть возможность выполнить то же самое действие.
2. Кроме того, я внедрю ваше решение и посмотрю, имеет ли оно какое-то значение
3. Спасибо, это сделало все быстрее
Ответ №2:
Правильного освобождения базовых COM-объектов недостаточно для вашей цели. Вместо перебора всех элементов в папке вам нужно использовать методы Find
/ FindNext
или Restrict
Items
класса для поиска элементов с вложениями, и только тогда вы сможете перебирать все элементы только с вложениями. В запросе может использоваться нотация SQL (VBA):
query ="@SQL=" amp; chr(34) amp; "urn:schemas:httpmail:hasattachment" amp; chr(34) amp; "=1"
Подробнее об этих методах читайте в следующих статьях:
- Как: Используйте методы поиска и FindNext для извлечения почтовых элементов Outlook из папки (C#, VB.NET)
- Как: Используйте метод ограничения для извлечения элементов почты Outlook из папки
Также вы можете найти AdvancedSearch
полезным метод класса приложения. Ключевыми преимуществами использования этого AdvancedSearch
метода в Outlook являются:
- Поиск выполняется в другом потоке. Вам не нужно запускать другой поток вручную, так
AdvancedSearch
как метод запускает его автоматически в фоновом режиме. - Возможность поиска любых типов товаров: почта, встреча, календарь, заметки и т.д. в любом месте, т. е. за пределами определенной папки. Методы
Restrict
иFind
/FindNext
могут быть применены к определеннойItems
коллекции (см.Items
СвойствоFolder
класса в Outlook). - Полная поддержка запросов DASL (пользовательские свойства также могут использоваться для поиска). Вы можете прочитать больше об этом в статье о фильтрации в MSDN. Для повышения производительности поиска можно использовать ключевые слова мгновенного поиска, если для магазина включен мгновенный поиск (см.
IsInstantSearchEnabled
СвойствоStore
класса). - Вы можете остановить процесс поиска в любой момент, используя
Stop
методSearch
класса.
См. раздел Расширенный поиск в Outlook программно: C#, VB.NET для получения дополнительной информации.