如何释放Outlook MailItem正确?

时间:2010-12-14 09:03:45

标签: c# com outlook mailitem

我无法发布我的Outlook MailItems。打开200 Mails后,Exchange Sever返回达到的最大打开电子邮件。

我将从所有选定的邮件中删除我的UserProperty。

我的代码:


foreach (var selection in Globals.ThisAddIn.Application.ActiveExplorer().Selection)
{
 if (selection is MailItem)
 {
  MailItem mi = (MailItem)selection;
  UserProperty up = mi.UserProperties.Find("MyProp");
  if (up != null)
  {
   up.Delete();
   //##################################
   // I also tried :
   //----------------------------------
   //    Marshal.ReleaseComObject(up);
   //    up = null;
   //----------------------------------
  }

  mi.Save();

  //##################################
  // I also tried :
  //----------------------------------
  //     mi.Close(OlInspectorClose.olDiscard);
  //----------------------------------


  // I don't know if this loop is necessary, but I have found it somewhere on the web
  while (Marshal.ReleaseComObject(mi) > 0);
  mi = null;

  //##################################
  // I also tried :
  //----------------------------------
  //    GC.Collect();
  //    GC.WaitForPendingFinalizers();
  //----------------------------------
 }
}

知道什么是错的吗?

5 个答案:

答案 0 :(得分:3)

您可以尝试以下操作:您可以在MailItem循环内定义For,也可以在班级级别定义mi,而不是在For循环中定义新的MailItem mi; foreach (var selection in Globals.ThisAddIn.Application.ActiveExplorer().Selection) { if (selection is MailItem) { mi= (MailItem)selection; // your other code... } } mi=null; GC.Collect(); GC.WaitForPendingFinalizers(); ,并为每个邮件项目重复使用它? e.g:

Outlook.Explorer myExplorer=Application.ActiveExplorer(); 
Outlook.Selection mySelection=myexplorer.Selection; 
foreach (var selection in mySelection)
{
}
myExplorer=null;
mySelection=null;
//....

编辑:

尝试为每个引用创建局部变量,例如:

{{1}}

修改-2:

如果您使用的是Outlook 2010,请检查以下内容: Outlook 2010 addin selection not clearing

答案 1 :(得分:3)

我相信像Bolu这样的任何一种错误。 再次非常感谢你帮助Bolu。

我现在正在使用以下解决方法:

List entryids = new List();

foreach (var selection in Globals.ThisAddIn.Application.ActiveExplorer().Selection)
{
    MailItem mi = selection as MailItem;
    if (mi != null)
    {
        // For any reason it's not possible to change the mail here

        entryids.Add(mi.EntryID);

        Marshal.ReleaseComObject(mi);
        mi = null;

    }
}

foreach (string id in entryids)
{
    MailItem mi = Globals.ThisAddIn.Application.ActiveExplorer().Session.GetItemFromID(id);

    // My changes on the mail

    mi.Save();
    Marshal.ReleaseComObject(mi);
    mi = null;
}

答案 2 :(得分:1)

尝试用for循环替换foreach并执行以下操作

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

同时删除对您可能正在使用的任何Outlook COM对象的所有引用。

答案 3 :(得分:1)

将释放方法置于主if条件之外。即使您使用foreach循环遍历它们,项也会被引用。 写

Marshal.ReleaseComObject(mi)

在最后一个“}”之前。这适合我。我读到通常你必须明确释放每个COM对象。

答案 4 :(得分:1)

您使用的是多点符号(mi.UserProperties.Find),这意味着编译器会创建一个隐式变量来保存mi.UserProperties调用的结果;您不能显式释放该变量。该对象拥有对其父MailItem对象的引用。

将其存储在显式变量中,然后使用Marshal.ReleaseComObject显式释放它。与UserProperty up变量相同。

此外,请勿将foreach与Outlook集合一起使用-该循环保留对所有项目的引用,直到循环退出。使用for循环并在循环的每个步骤上显式释放项目后,立即释放该项目

  Selection selectedItems = Globals.ThisAddIn.Application.ActiveExplorer().Selection; 
  for (int i = 1; i <= selectedItems .Count; i++)
  {
    object selection= selectedItems[i];
    MailItem mi = selection as MailItem;
    if (mi != null) //can have items other than MailItem
    {
      UserProperties props = mi.UserProperties;
      UserProperty up = props .Find("MyProp");
      if (up != null)
      {
        ...
        Marshal.ReleaseComObject(up);
      };
      Marshal.ReleaseComObject(props);
      Marshal.ReleaseComObject(mi);
    }; //if   
    Marshal.ReleaseComObject(selection);
  }; //for