0

我正在开发一个 WPF 应用程序来监视 Outlook 共享邮箱中的多个文件夹。我已将 ItemAdd 和 ItemRemove 事件处理程序连接到 Folder.Items 对象。

一切都很好用了几分钟。但随着时间的推移,事件处理似乎变得“噗嗤”一声。一些文件夹仍然可以识别添加和删除,其他文件夹只会看到删除,而其他文件夹则对任何活动视而不见。对我来说,似乎事件处理程序正在被垃圾收集,但我的 Items 对象被声明为它所在的类中的全局变量,所以我看不出它们是如何被 GC 淘汰的。

Outlook Folder.Items 事件有什么我应该注意的陷阱吗?我有一个以前的更简单的应用程序,它通过类似的过程工作,可以在很长一段时间内正常工作。就项目事件处理而言,我的旧应用程序和这个新应用程序之间没有本质区别。我真的不知道是什么原因造成的。

下面是相关代码。为了带来一些上下文,我正在做的是,对于 Outlook 共享邮箱中的每个文件夹,都会创建一个“TicketView”用户控件,它代表该文件夹的内容(MailItems)。这个 TicketView 是一个简单的 ListBox,它可能包含 0 到几十个 MailItems - 没有太多。

public partial class TicketView : UserControl
    {
        private Folder _thisFolder = null;
        private TicketCollection _thisTicketColl = null;
        private Items _thisItems = null;

        public TicketView(Folder folder)
        {
            InitializeComponent();

            _thisTicketColl = this.FindResource("TicketCollection") as TicketCollection;
            _thisFolder = folder;
            _thisItems = folder.Items;

            SetFolderEvents();
            Refresh();
        }

        private void SetFolderEvents()
        {
            _thisItems.ItemAdd += new ItemsEvents_ItemAddEventHandler(delegate
                {
                    Refresh();
                });

            _thisItems.ItemRemove += new ItemsEvents_ItemRemoveEventHandler(delegate
                {
                    Refresh();
                });
        }

        public void Refresh()
        {
            BackgroundWorker worker = new BackgroundWorker();

            worker.DoWork += new DoWorkEventHandler(delegate(object sender, DoWorkEventArgs e)
            {
                string[] fields = new string[] { "Subject", "SenderName", "SentOn", "EntryID" };
                var olTable = TicketMonitorStatics.GetOutlookTable(_thisFolder, fields, filter);
                olTable.Sort("SentOn", true);
                var refreshedList = new List<Ticket>();

                while (!olTable.EndOfTable)
                {
                    var olRow = olTable.GetNextRow();
                    refreshedList.Add(new Ticket
                    {
                        Subject = olRow["Subject"],
                        Sender = olRow["SenderName"],
                        SentOn = olRow["SentOn"],
                        EntryID = olRow["EntryID"]
                    });
                };
                e.Result = refreshedList;
            });

            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object sender, RunWorkerCompletedEventArgs e)
            {
                var refreshedList = e.Result as List<Ticket>;
                UpdateTicketList(refreshedList);

                worker.Dispose();
            });

            worker.RunWorkerAsync();
        }

        private void UpdateTicketList(List<Ticket> newList)
        {
            _thisTicketColl.Clear();

            foreach (Ticket t in newList)
            {
                _thisTicketColl.Add(t);
            }
        }
    }
}
4

1 回答 1

1

Outlook 事件不应用于任何类型的同步。它们被设计为仅用于 UI 目的,并且可以在负载过重或发生网络错误(如果您使用在线商店)时丢弃。

您只能将事件用作代码需要尽快运行而不是稍后运行的提示。

您可以使用 IExchangeExportChanges MAPI 接口(仅限 C++ 或 Delphi)执行同步;这与 Outlook 用于同步其缓存文件夹的 API 相同。如果您不使用 C++ 或 Delphi,则可以使用 Redemption 及其 RDOFolderSynchronizer 对象 ( http://www.dimastr.com/redemption/rdofoldersynchronizer.htm )

于 2013-03-10T16:16:33.190 回答