【发布时间】:2015-12-03 23:31:14
【问题描述】:
我开发了一个 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());
到目前为止一切顺利。但是现在我想在没有 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() 抛出 InvalidOperationException,“当前 SynchronizationContext 不能用作 TaskScheduler。” */
请注意,我尝试在插件初始化中创建一个 TaskScheduler,并按照建议 here 将其放入单例中。但它不起作用,继续任务不是在所需的 VSTA 主线程中执行,而是在另一个(用 VisualStudio 检查)中执行。
有什么想法吗?
【问题讨论】:
-
你试过异步/等待吗?
-
不,我没有,因为我的目标是 .NET40。升级到 .NET45 目前不是一个选项。但是,您是对的,我会尝试一下,这可能会为 40 年的修复带来一些见解。
-
@DmitryStreblechenko 不幸的是,在 await 关键字之后,执行其余任务的线程不是主 VSTA 线程。
-
请出示您的异步/等待代码。
标签: c# multithreading outlook vsto outlook-addin