5

OutlookMailItemsを解放できません。200通のメールを開いた後、Exchangeサーバーは開いている最大のメールを返します。

選択したすべてのメールから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();
  //----------------------------------
 }
}

何が問題なのか分かりますか?

4

5 に答える 5

3

これを試すことができます:ループMailItem内で毎回新しいものを定義する代わりに、ループ外またはクラスレベルでさえ定義し、それを各メールアイテムに再利用できますか?例えば:FormiFor

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();

編集:

参照ごとにローカル変数を作成してみてください。例:

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

編集-2:

Outlook 2010を使用している場合は、次を確認してください: Outlook2010アドインの選択がクリアされない

于 2010-12-14T10:28:03.873 に答える
3

ボルが言ったようなどんな種類のバグでもあると思います。もう一度、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;
}
于 2010-12-14T13:38:56.617 に答える
2

foreachをforループに置き換えて、次の手順を実行してください

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

また、使用している可能性のあるOutlookCOMオブジェクトへのすべての参照を削除します。

于 2010-12-14T10:48:29.797 に答える
1

リリースメソッドをメインif条件の外に置くだけです。foreachループでアイテムをループするだけでも、アイテムは参照されます。書く

Marshal.ReleaseComObject(mi)

最後の""の直前}。これは私のために働きます。通常、すべてのCOMオブジェクトを明示的に解放する必要があることを読みました。

于 2012-01-29T12:41:59.237 に答える
1

複数のドット表記()を使用しています。これは、コンパイラが呼び出しmi.UserProperties.Findの結果を保持する暗黙の変数を作成することを意味します。mi.UserPropertiesその変数を明示的に解放することはできません。そのオブジェクトは、その親MailItemオブジェクトへの参照を保持します。

明示的な変数に格納し、を使用して明示的に解放しMarshal.ReleaseComObjectます。UserProperty up変数についても同様です。

また、Outlookコレクションでは使用しないでくださいforeach。このループは、ループが終了するまですべてのアイテムへの参照を保持します。ループを使用し、そのアイテムを使い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  
于 2018-12-01T18:43:03.980 に答える