Reputation: 23
I am having issues with looping through the emails in outlook inbox folders (C# VSTO add in Outlook). I was using foreach loop but it consumes a lot of memory and then causes the exception: out of system/memory resources. So, I am using for loop now which does not cause that error but for one of the folders it is really slow, reads less than 5-8 emails per second. This folder contains a bit more than 100,000 emails. For all other folders the speed is between 30-35 emails.
The code is:
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);
}
It would be great if someone can help with this issue. While using foreach loop the speed was approx. 40-45 emails per second. Also, this method is called from another for loop which iterates through the folders, Thanks in advance
Upvotes: 1
Views: 299
Reputation: 49395
Properly releasing underlying COM objects is not enough for your goal. Instead of iterating over all items in the folder you need to use the Find
/FindNext
or Restrict
methods of the Items
class to find items with attachments and only then you can iterate over all items with attachments only. The query may use the SQL notation (VBA):
query ="@SQL=" & chr(34) & "urn:schemas:httpmail:hasattachment" & chr(34) & "=1"
Read more about these methods in the following articles:
Also you may find the AdvancedSearch
method of the Application class helpful. The key benefits of using the AdvancedSearch
method in Outlook are:
AdvancedSearch
method runs it automatically in the background.Restrict
and Find
/FindNext
methods can be applied to a particular Items
collection (see the Items
property of the Folder
class in Outlook).IsInstantSearchEnabled
property of the Store
class).Stop
method of the Search
class.See Advanced search in Outlook programmatically: C#, VB.NET for more information.
Upvotes: 1
Reputation: 66215
Firstly, looping through all items in a folder is not good idea. Do you really need to do that?
You keep retrieving the Items collection in the loop (folder.Items[k]
). Cache Items
before entering the loop:
Items items = folder.Items;
for (int k = 1; k <= items.Count; k++)
{
object item = items[k];
...
}
Marshal.ReleaseComObject(items);
You are leaking references (they will later will released by the GC of course), but since you are using FinalReleaseComObject...
object item = items[k];
MailItem mailItem = item as MailItem;
if (mailItem != null)
{
...
Marshal.ReleaseComObject(mailItem);
}
Marshal.ReleaseComObject(item);
Upvotes: 0