Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get the continuation after an await to execute on the same thread?

As I recently discovered to my cost, doing an await when there's no synchronization context may result in the code after the await being executed on a different thread.

I'm currently having problems with strange behaviour in a VSTO office add-in, which I think is possibly a result of this behaviour. When processing events raised by the Office application, there's no synchronization context in place (unless I create a form, which will create a synchronization context).

My question is whether creating a form is the best / most efficient way to ensure that I have a synchronization context, or whether there's a simpler way to do it.

like image 330
Gary McGill Avatar asked Oct 05 '12 22:10

Gary McGill


People also ask

Is async await on the same thread?

The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active.

Does await make it synchronous?

Async/await helps you write synchronous-looking JavaScript code that works asynchronously. Await is in an async function to ensure that all promises that are returned in the function are synchronized. With async/await, there's no use of callbacks.

Does await pause the thread?

Asynchronous MethodsWhen the executing thread reaches an await expression, it hits the “pause” button and the method execution is suspended. When the task being awaited completes, it hits the “play” button, and the method execution is resumed.

Does await task delay block thread?

Delay will create a task which will complete after a time delay. Task. Delay is not blocking the calling thread so the UI will remain responsive.


2 Answers

Office apps do invoke their events in an STA context, but they do not provide an appropriate SynchronizationContext.

The easiest way to work around this is explained on my blog in SynchronizationContext Odds and Ends, where I briefly describe a couple of miscellaneous things that I found while doing research for my article but just weren't important enough to include. To fix this problem, at the beginning of every event, do this:

SynchronizationContext.SetSynchronizationContext(
    new WindowsFormsSynchronizationContext());

Any awaits after that should resume on the STA thread.

like image 56
Stephen Cleary Avatar answered Oct 02 '22 00:10

Stephen Cleary


You might want to check out this article, which describes how to set up a SynchronizationContext without a message pump. Note that this is really only useful if you expect to have other work that you intend to await (queuing up multiple callbacks.) If you only ever await one thing at a time, your code might as well just run synchronously, since you don't have anything else to do with your idle time, like run a message pump.

like image 39
Dan Bryant Avatar answered Oct 01 '22 23:10

Dan Bryant