钩子事件Outlook VSTO在主线程上继续工作

时间:2015-09-08 10:16:52

标签: c# multithreading outlook vsto outlook-addin

我开发了一个Outlook VSTO插件。某些任务应该在后台线程上完成。通常,检查本地数据库中的某些内容或调用Web请求。在阅读了几篇文章之后,我放弃了在后台线程中调用Outlook对象模型(OOM)的想法。

我有一些wpf控件,我成功地设法使用.NET 40 TPL执行异步任务,并在完成后完成"完成"主要VSTA线程中的作业(即访问UI或OOM)。

为此,我使用以下形式的语法:

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,&#39;当前的SynchronizationContext可能不会被用作TaskScheduler。&#39; * /

请注意,我尝试在addin初始化中创建一个TaskScheduler,并按照建议here将其放入单例中。但它不起作用,延续任务不是在所需的VSTA主线程中执行,而是在另一个线程中执行(使用VisualStudio进行检查)。

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

您可以使用SynchronizationContext类,该类提供在各种同步模型中传播同步上下文的基本功能。 Post方法将异步消息调度到同步上下文,即Post方法启动异步请求以发布消息。有关详细信息和示例代码,请参阅Using SynchronizationContext for sending events back to the UI for WinForms or WPF

FYI Current属性允许获取当前线程的同步上下文。此属性对于将同步上下文从一个线程传播到另一个线程非常有用。