Подтвердить что ты не робот

Перехваченные события Outlook VSTO продолжает работу на главной теме

Я разработал Outlook VSTO addin. Некоторые задачи должны выполняться в фоновом потоке. Как правило, проверка чего-то в моем локальном db или вызов веб-запроса. После чтения нескольких сообщений я отказался от идеи вызова объектной модели Outlook (OOM) в фоновом потоке.

У меня есть некоторые элементы управления wpf, и я успешно смог использовать .NET 40 TPL для выполнения задачи async, а после завершения - "завершить" задание (например, доступ к пользовательскому интерфейсу или OOM) в основном VSTA-потоке.

Для этого я использую синтаксис формы:

Task<SomeResult> task = Task.Factory.StartNew(()=>{
    //Do long tasks that have nothing to do with UI or OOM
    return SomeResult();
});

//now I need to access the OOM
task.ContinueWith((Task<SomeResult> tsk) =>{
   //Do something clever using SomeResult that uses the OOM
},TaskScheduler.FromCurrentSynchronizationContext());

Пока все хорошо. Но теперь я хочу сделать что-то подобное при подключении события в OOM, где нет элемента управления Form/WPF. Именно моя проблема возникает из-за того, что TaskScheduler.FromCurrentSynchronizationContext() генерирует исключение.

Например,

Items inboxItems = ...;
inboxItems.ItemAdd += AddNewInboxItems;

private void AddNewInboxItems(object item)
{
    Task<SomeResult> task = Task.Factory.StartNew(()=>{
    //Do long tasks that have nothing to do with OOM
    return SomeResult()});


   var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
   /* Ouch TaskScheduler.FromCurrentSynchronizationContext() throws an  InvalidOperationException, 'The current SynchronizationContext may not be used as    a TaskScheduler.' */
   task.ContinueWith((Task<SomeResult> tsk) =>{
       //Do something clever using SomeResult that uses the OOM
   }),scheduler};
}

/* Ouch TaskScheduler.FromCurrentSynchronizationContext() выдает исключение InvalidOperationException: "Текущий SynchronizationContext не может использоваться как TaskScheduler". */

Обратите внимание, что я попытался создать TaskScheduler в инициализации addin и поместив его в одноэлементный, как предлагается здесь. Но он не работает, задача продолжения не выполняется в нужном главном потоке VSTA, а другая (проверяется с помощью VisualStudio).

Любая идея?

4b9b3361

Ответ 1

Известно, что SynchronizationContext.Current может быть null в нескольких местах, где он не должен (включая надстройки офиса). Эта ошибка была исправлена ​​в .NET 4.5. Но так как вы не можете перейти на .NET 4.5, вам нужно найти обходной путь. В качестве предложения попробуйте сделать:

System.Threading.SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());

при инициализации вашего аддона.

Ответ 2

Вы можете использовать класс SynchronizationContext, который предоставляет базовые функции для распространения контекста синхронизации в различных моделях синхронизации. Метод Post отправляет асинхронное сообщение в контекст синхронизации, то есть метод Post запускает асинхронный запрос для публикации сообщения. См. Использование SynchronizationContext для отправки событий обратно в интерфейс для WinForms или WPF для получения дополнительной информации и примера кода.

FYI Свойство Current позволяет получить контекст синхронизации для текущего потока. Это свойство полезно для распространения контекста синхронизации из одного потока в другой.