钩子事件Outlook VSTO在主线程上继续工作
本文关键字:线程 继续 工作 事件 Outlook VSTO | 更新日期: 2023-09-27 18:11:37
我开发了一个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());
到目前为止一切顺利。但是现在我想在没有表单/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()抛出InvalidOperationException, '当前的SynchronizationContext可能不会被用作TaskScheduler。‘*/
请注意,我尝试在插件初始化中创建一个TaskScheduler,并将其放在这里建议的单例中。但是它不起作用,延续任务不是在所需的VSTA主线程中执行,而是在另一个主线程中执行(用VisualStudio检查)。
有一个已知的错误,即SynchronizationContext。Current在一些不应该为空的地方(包括办公室外接程序)可能为空。这个bug在。net 4.5中得到了修复。但是因为你不能升级到。net 4.5,你必须找到一个解决方法。作为建议,试着这样做:
System.Threading.SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
您可以使用SynchronizationContext类,它提供了在各种同步模型中传播同步上下文的基本功能。Post方法将异步消息分派到同步上下文,即Post方法启动一个异步请求来发布消息。更多信息和示例代码请参见使用SynchronizationContext将事件发送回WinForms或WPF的UI。
供参考:Current属性允许获取当前线程的同步上下文。此属性用于将同步上下文从一个线程传播到另一个线程。