我开发了一个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进行检查)。
有什么想法吗?
答案 0 :(得分:3)
您可以使用SynchronizationContext类,该类提供在各种同步模型中传播同步上下文的基本功能。 Post方法将异步消息调度到同步上下文,即Post方法启动异步请求以发布消息。有关详细信息和示例代码,请参阅Using SynchronizationContext for sending events back to the UI for WinForms or WPF。
FYI Current属性允许获取当前线程的同步上下文。此属性对于将同步上下文从一个线程传播到另一个线程非常有用。