加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 通过邮件项目循环内存不足

发布时间:2020-12-15 23:23:19 所属栏目:百科 来源:网络整理
导读:嗨,我有一个Outlook com插件,正在为我做一些简单的搜索技巧.我是将它放在一起的一部分,但我遇到了内存不足的问题.这个过程非常简单,基本上循环遍历outlook文件夹,检查每个mailItem是否匹配.给定循环重新初始化变量每次我都希望垃圾收集器跟上,但是当我观察内
嗨,我有一个Outlook com插件,正在为我做一些简单的搜索技巧.我是将它放在一起的一部分,但我遇到了内存不足的问题.这个过程非常简单,基本上循环遍历outlook文件夹,检查每个mailItem是否匹配.给定循环重新初始化变量每次我都希望垃圾收集器跟上,但是当我观察内存时,它会丢失~10m / sec,直到系统内存不足并且我得到未处理的异常.

这是代码的一部分

private void FindInFolder(Outlook.MAPIFolder FolderToSearch)
    {
        Outlook.MailItem mailItem;
        Outlook.MAPIFolder ParentFolder;

        int counter = 0;

        StatusBar.Text = "Searching in Folder " + FolderToSearch.FolderPath + "/" + FolderToSearch.Name;
        StatusBar.Update();
        this.Update();

        foreach (COMObject item in FolderToSearch.Items)
        {
            counter++;
            if (counter % 100 == 0)
            {
                StatusBar.Text = FolderToSearch.FolderPath + "/" + FolderToSearch.Name + " item " + counter + " of " + FolderToSearch.Items.Count;
                StatusBar.Update();
                if (counter % 1000 == 0)
                {
                    GC.Collect();
                }
            }
            if (item is Outlook.MailItem)
            {
                mailItem = item as Outlook.MailItem;
                if (IsMatch(mailItem))
                {
                    if (mailItem.Parent is Outlook.MAPIFolder)
                    {
                            ParentFolder = mailItem.Parent as Outlook.MAPIFolder;
                            ResultGrd.Rows.Add(mailItem.EntryID,ParentFolder.FolderPath,mailItem.SenderName,mailItem.Subject,mailItem.SentOn);
                    }
                }
            }
            mailItem = null;
        }
    }

哪个电话

private Boolean IsMatch(Outlook.MailItem inItem)
    {
        Boolean subBool = false;
        Boolean NameBool = false;

        try
        {
            if (null != inItem)
            {
                if (SubjectTxt.Text != "")
                {
                    if (inItem.Subject.Contains(SubjectTxt.Text))
                    {
                        subBool = true;
                    }
                }
                else
                {
                    subBool = true;                    
                }

                if (NameTxt.Text != "")
                {
                    if (inItem.Sender != null)
                    {
                        if (inItem.Sender.Name.Contains(NameTxt.Text))
                        {
                            NameBool = true;
                        }
                    }
                }
                else 
                {
                    NameBool = true;
                }

                return subBool && NameBool;

            }
        }
        catch (System.Runtime.InteropServices.COMException ce)
        {
            if (ce.ErrorCode == -2147467259)
            {
                //DO nothing just move to the next one
            }
            else
            {
                MessageBox.Show("Crash in IsMatch error code = " + ce.ErrorCode + " " + ce.InnerException);
            }
        }
        return false;
    }

请原谅底部的所有错误捕获部分和GC.collect它们是我尝试找出错误并释放内存的一些尝试.

请注意,FindInFolder也会被新线程调用,因此我可以在继续搜索时与结果进行交互.

到目前为止我尝试了什么:

使变量本地化为函数而不是类,因此G可以检索,但是’item’中最常用的变量因为它是foreach的一部分,所以它必须以这种方式声明.

每1000个mailItems做一个手动GC,这没有任何区别.

由于某种原因,它需要大量的内存只是循环遍历项目,GC永远不会释放它们.

请注意我使用的是netoffice而不是VSTO for Com addin.

解决方法

首先:这是NetOffice代码,你不需要NetOffice中的Marshal.ReleaseComObject. (此外,此处调用ReleaseComObject无用)代替实例使用Dispose().

请记住:NetOffice为您处理COM代理(这就是为什么它允许在NetOffice中使用两个2点).
在你的情况下,它的内部存储为:
// FolderToSearch
??????? – 物品
???????????–Enumerator
??????????????? – 项目
??????????????? – 项目
??????????????? – ….

在每个循环结束时使用item.Dispose()来删除/释放项目实例或在foreach之后使用以下内容

FolderToSearch.Dipose()
// dispose文件夹实例和所有代理来自

FolderToSearch.DisposeChildInstances()
//配置所有代理来自但保持文件夹实例存活

下一个:
这里的Items枚举器是一个自定义枚举器(由NetOffice提供)
然而,它适用于少量的项目,但不要做更多
较重的场景(可以交换服务器和数千个项目).本地工作站/程序无法在内存中处理此问题.因此,Microsoft仅提供了良好的GetFirst / GetNext模式.在NetOffice中,它看起来像:

Outlook._Items items = FolderToSearch.Items;
COMObject item = null;
do
{
    if (null == item)
       item = items.GetFirst() as COMObject;
    if (null == item)
       break;

    // do what you want here

    item.Dispose();
    item = items.GetNext() as COMObject;
} while (null != item);

这也应该有效.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读