События папки Outlook случайно перестают работать в общем почтовом ящике
Я работаю над приложением WPF, которое отслеживает многочисленные папки в общем почтовом ящике Outlook. Я подключил обработчики событий ItemAdd и ItemRemove к объекту Folder.Items.
Все отлично работает в течение нескольких минут. Но с течением времени обработка событий, кажется, идет "пуф". Некоторые папки по-прежнему распознают добавление и удаление, другие видят только удаления, а другие не видят никаких действий. Мне кажется, что обработчики событий собираются мусором, но мой объект Items объявлен как глобальная переменная в классе, в котором он находится, поэтому я не вижу, как они могут быть GC-out.
Есть ли какие-либо подводные камни, о которых мне следует знать в событиях 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 ответ
События Outlook не должны использоваться для какой-либо синхронизации. Они предназначены для использования только в целях пользовательского интерфейса и могут быть отброшены при больших нагрузках или при возникновении сетевой ошибки (если вы используете интернет-магазин).
Вы можете использовать события только как подсказку, что ваш код должен запускаться раньше, а не позже.
Вы можете использовать интерфейс MAPI IExchangeExportChanges (только C++ или Delphi) для выполнения синхронизации; это тот же API, который используется Outlook для синхронизации его кэшированных папок. Если вы не используете C++ или Delphi, вы можете использовать Redemption и его объект RDOFolderSynchronizer ( http://www.dimastr.com/redemption/rdofoldersynchronizer.htm).