挂钩事件 Outlook VSTO 在主线程上继续工作
Hooked events Outlook VSTO continuing job on main Thread
我开发了一个 Outlook VSTO 插件。有些任务应该在后台线程上进行。通常,检查我本地数据库中的某些内容或调用 Web 请求。阅读几篇文章后,我放弃了在后台线程中调用 Outlook 对象模型 (OOM) 的想法。
我有一些 wpf 控件,我成功地使用 .NET 40 TPL 执行异步任务,完成后 "finish" 作业(即访问 UI 或 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());
到目前为止一切顺利。但是现在我想在没有 Form/WPF 控件的 OOM 中挂钩事件时做类似的事情。准确地说,我的问题来自 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() throws an InvalidOperationException, 'The current SynchronizationContext may not be used as a TaskScheduler.' */
请注意,我尝试在加载项初始化中创建一个 TaskScheduler,并按照建议将其放入单例中 here。但它不起作用,继续任务不是在所需的 VSTA 主线程中执行,而是在另一个线程中执行(使用 VisualStudio 检查)。
有什么想法吗?
您可以使用 SynchronizationContext class which provides the basic functionality for propagating a synchronization context in various synchronization models. The Post method dispatches an asynchronous message to a synchronization context, i.e. the Post method starts an asynchronous request to post a message. See Using SynchronizationContext for sending events back to the UI for WinForms or WPF 获取更多信息和示例代码。
仅供参考 Current 属性 允许获取当前线程的同步上下文。此 属性 对于将同步上下文从一个线程传播到另一个线程很有用。
存在一个已知错误,即 SynchronizationContext.Current 可能在多个不应该为 null 的地方(包括 Office 加载项)。该错误已在 .NET 4.5 中修复。但由于您无法升级到 .NET 4.5,因此您必须找到解决方法。作为建议,尝试做:
System.Threading.SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
初始化插件时。
我开发了一个 Outlook VSTO 插件。有些任务应该在后台线程上进行。通常,检查我本地数据库中的某些内容或调用 Web 请求。阅读几篇文章后,我放弃了在后台线程中调用 Outlook 对象模型 (OOM) 的想法。
我有一些 wpf 控件,我成功地使用 .NET 40 TPL 执行异步任务,完成后 "finish" 作业(即访问 UI 或 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());
到目前为止一切顺利。但是现在我想在没有 Form/WPF 控件的 OOM 中挂钩事件时做类似的事情。准确地说,我的问题来自 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() throws an InvalidOperationException, 'The current SynchronizationContext may not be used as a TaskScheduler.' */
请注意,我尝试在加载项初始化中创建一个 TaskScheduler,并按照建议将其放入单例中 here。但它不起作用,继续任务不是在所需的 VSTA 主线程中执行,而是在另一个线程中执行(使用 VisualStudio 检查)。
有什么想法吗?
您可以使用 SynchronizationContext class which provides the basic functionality for propagating a synchronization context in various synchronization models. The Post method dispatches an asynchronous message to a synchronization context, i.e. the Post method starts an asynchronous request to post a message. See Using SynchronizationContext for sending events back to the UI for WinForms or WPF 获取更多信息和示例代码。
仅供参考 Current 属性 允许获取当前线程的同步上下文。此 属性 对于将同步上下文从一个线程传播到另一个线程很有用。
存在一个已知错误,即 SynchronizationContext.Current 可能在多个不应该为 null 的地方(包括 Office 加载项)。该错误已在 .NET 4.5 中修复。但由于您无法升级到 .NET 4.5,因此您必须找到解决方法。作为建议,尝试做:
System.Threading.SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
初始化插件时。