2013-05-12 5 views
4

Я работаю над Outlook Addin, и мне приходится обрабатывать большое количество элементов. Это занимает довольно много времени, и поэтому я попытался выполнить обработку в другом потоке (используя Task.Factory.StartNew). Однако это приводит к случайному сбою Outlook.Outlook Addin: Работа с потоками

Я использую Redemption для работы с MAPITable, чтобы уменьшить нагрузку и загрузить только релевантные данные.

  • Я попытался инициализировать мою RDOSession как из моего основного потока, так и из моего рабочего потока.
  • Я пытался получать MAPIFolders в основном потоке, и работает только с MAPITable на рабочий поток

В настоящее время, единственное, что работает для меня работает всю свою логику на главном потоке (в событии нажатия кнопки), однако это блокирует пользовательский интерфейс Outlook в течение длительного периода времени, что неприемлемо с точки зрения пользователя.

Есть ли у кого-нибудь указатель на то, как работать с фоновыми потоками из Outlook Addin?

ответ

3

Имея подобный код в моем проекте я хотел бы предложить следующее:

  1. Создать новую нить, используя класс Thread и установить его квартиру STA.

  2. Loggin для сеанса с использованием «session.Logon (« имя_файла », NoMail: true, NewSession: false); и не используя MAPIOBJECT. Я обнаружил, что он имеет лучшую производительность, чем использование MAPIOBJECT. Думаю, он по-прежнему марширует некоторые обратные вызовы в основной поток, поскольку MAPIOBJECT был создан в основном потоке.

  3. Используйте «Marshal.ReleaseComObject» для каждого COM-объекта, который вы используете, как только закончите с ними. Вероятно, это то, что вызывает нестабильность, поскольку Outlook действительно не нравится, когда объект слишком длинный. Например, эта строка кода «var table = rdoFolder.Items.MAPITable;» создайте два COM-объекта: RDOItems и MAPITable, оба из них должны быть выпущены, поэтому вам нужно разделить эту строку, чтобы сохранить ссылку на объект RDOItems.

  4. Вызов GC.Collect и Application.DoEvents, потому что если вы не вызываете Marshal.ReleaseComObject на всех COM-объекта финализации будет пытаться освободить их и будет висеть, потому что были созданы COM-объекты на потоке, который не насос цикл обработки сообщений, и это метод финализатора должен запускаться в потоке, который их создал.

  5. Если вы можете, выполните дополнительный процесс и выполните этот цикл в отдельном процессе. Это обеспечит максимальное разделение между пользовательским интерфейсом и фоновой работой.

1

В чем проблема с использованием объектов RDO во вторичной резьбе? Пока RDOSession создается во вторичном потоке, MAPI должен быть правильно инициализирован.

Кроме того, TaskFactory использует пул потоков, вам будет лучше использовать явный класс Thread, o хотя бы убедиться, что RDOSession не используется между разными потоками - MAPI должен быть инициализирован в каждом потоке.

+0

Вот пример нерабочим кода, что приводит к Outlook, сбой: https://gist.github.com/saguiitay/5565244 – SaguiItay

+0

Попытка переменной Объем RDOSession с помощью {} и вызвать GC.Collect(); ведь объекты RDO не входят в сферу действия. –