Outlook文件夹事件随机停止在共享邮箱上工作

时间:2013-03-10 15:44:49

标签: outlook wpf-controls mapi public-folders

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

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

我是否应该注意Outlook Folder.Items事件的任何陷阱?我有一个以前更简单的应用程序,它通过类似的过程工作,可以在很长一段时间内正常工作。就我的旧应用程序和新应用程序之间的Item事件处理而言,没有内在差异。我真的不知道是什么导致了这一点。

以下是相关代码。为了给这个带来一些上下文,我正在做的是,对于Outlook共享邮箱中的每个文件夹,创建一个“TicketView”UserControl,它代表该文件夹的内容(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);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

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

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

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