任务和STA / MTA线程模型 [英] Task and STA / MTA Threading Model

查看:105
本文介绍了任务和STA / MTA线程模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


在我们的Outlook集成(Managed COM AddIn C#)中,我们正在使用Tasks在后台执行一些工作。


<嗯,在我们的一个客户的机器上,当我们在Outlook中打开一个Dialog时,我们收到以下异常。


Beim aufrufenden Thread muss es sich um einen STA-Thread handeln ,dadiefürvieleKomponentenderBenutzeroberflächeerforderlichist。 (我的翻译:调用线程必须是STA-Thread,因为某些UI组件需要这样做

    bei System.Windows.Input.InputManager..ctor()

    bei System.Windows.Input.InputManager.GetCurrentInputManagerImpl()

    bei PresenceProfiles。< OnIsVisibleChanged> d__1.MoveNext()

--- EndederStappelüberwachungvomvorhergehenden Ort,dem dieAusnahmeausgelöstwurde---

    bei System.Runtime.CompilerServices.AsyncMethodBuilderCore。<> c。< ThrowAsync> b__6_1(对象状态)

    bei System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(对象状态)

    bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx)

    bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx)

    bei System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()

    bei System.Threading.ThreadPoolWorkQueue.Dispatch()

    bei System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()


我认为问题是,在任务完成后完成后,以下说明不会在Outlook主线程上下文中执行。如何强制执行任务完成后执行的指令在主线程上下文中执行。


祝你好运b
Christian


解决方案

这归结为awaiter配置。你没有发布你如何调用这个任务,所以我们完全在这里猜测。对于此讨论,假设您的插件正在响应UI事件而启动任务,因此调用代码是UI
线程。如果不是这样,那么问题就完全不同了。


当你启动任务时,它将在任意线程上运行。如果您正在使用async / await模式,则await之后的任何内容都将在UI线程上运行。你不需要做任何事情。

 async Task SomeUIMethodAsync()
{
//在UI线程上运行(假设)

//等待工作线程完成
await DoSomethingInTaskAsync();

//返回UI线程,因为你没有配置awaiter
}

但是如果你明确地创建任务,那么你需要告诉调度程序在调用线程上运行continuation(我假设你有)。

 void SomeUIWork( )
{
//捕获当前的同步上下文
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();

//这里不使用异步...
var task = Task.Run(()=> DoWorkOnTask())
.ContinueWith(()=> DoMoreWorkOntask ())
.ContinueWith(()=> DoUIWork(),scheduler);
}


Hi,

in our Outlook integration (Managed COM AddIn C#) we are using Tasks to execute some work in the background.

Well, on machines from one of our customers we receive the following exception, when one of our Dialogs is opened in Outlook.

Beim aufrufenden Thread muss es sich um einen STA-Thread handeln, da dies für viele Komponenten der Benutzeroberfläche erforderlich ist. (my translation: The calling Thread must be a STA-Thread, because this is required for some UI components)
   bei System.Windows.Input.InputManager..ctor()
   bei System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
   bei PresenceProfiles.<OnIsVisibleChanged>d__1.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.CompilerServices.AsyncMethodBuilderCore.<>c.<ThrowAsync>b__6_1(Object state)
   bei System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   bei System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   bei System.Threading.ThreadPoolWorkQueue.Dispatch()
   bei System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

I think, that the problem is, that after a Task is finished, the following instructions are not executed in Outlooks main thread context. How do I force, that the instructions, that are executed after a task is finished are executed in the main thread context.

Best regards
Christian

解决方案

This boils down to the awaiter configuration. You didn't post how you're calling that task so we're completely guessing here. For this discussion, it is assumed that your addin is starting the task in response to a UI event so the calling code is the UI thread. If this is not true then the problem is completely different.

When you start a task it'll run on an arbitrary thread. If you're using the async/await pattern then anything after that await will be running back on the UI thread. You don't need to do anything.

async Task SomeUIMethodAsync ()
{
   //Running on UI thread (assumption)

   //Wait for the worker thread to complete
   await DoSomethingInTaskAsync();

   //Back on UI thread because you didn't configure the awaiter   
}

But if you're creating the task explicitly then you need to tell the scheduler to run the continuation (which I assume you have) on the calling thread.

void SomeUIWork ()
{
   //Capture the current sync context
   var scheduler = TaskScheduler.FromCurrentSynchronizationContext();

   //Not using async here...
   var task = Task.Run(() => DoWorkOnTask())
                  .ContinueWith(() => DoMoreWorkOntask())
                  .ContinueWith(() => DoUIWork(), scheduler);
}


这篇关于任务和STA / MTA线程模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆