0

Before I use

protected async void OnResume() {
  await DoWorkAsync(); // assume exception is appropriately handled
  await DoOtherWorkAsync(); 
}

But now I saw other developers use

protected void OnResume() {
  SynchronizationContext.Current.Post(async (status) => {
  await DoWorkAsync(); 
  await DoOtherWorkAsync();}, null);
}

Is the second one correct and preferred when calling async methods inside non-async methods? Thank you in advance.

UPDATE: If you use the 2nd snippet, you must call SynchronizationContext.Current.Post() on UI Thread, or you will get NullReferenceException, cause SynchronizationContext.Current is null on non-UI Thread. _handler.Post(async() => {// do UI changes}); can be called on non-UI Thread to do any UI changes, as long as _handler is instantiated on UI Thread.

1
  • If You can make your method async - do it as it's a common patern nowadays. If it could possibly cause some troubles - You can use second solution as it is correct nothing bad about it Commented Nov 2, 2015 at 15:35

2 Answers 2

2

No, don't use SynchronizationContext. You're already on the UI thread, so the second option really makes no sense.

Note that normally async void should be avoided. In this case, I'd say it's acceptable because you're actually treating OnResume as though it were an event handler:

protected async void OnResume()
{
  await DoWorkAsync();
}
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks @Stephen, the second one throws null reference exception for SynchronizationContext.Current if SynchronizationContext.Current.Post is called from non-UIThread.
@macio.Jun: Probably because SynchronizationContext.Current is null.
Yeah, SynchronizationContext.Current is null. I really don't know why SynchronizationContext.Current is null when it's called on non-UIThread. MSDN says property Current Gets the synchronization context for the current thread.
@macio.Jun: It's because by default threads do not have a synchronization context. UI frameworks to add one to their UI threads because they need one. But in general, random thread pool threads are not going to have one.
Thanks @Stephen, UI frameworks added context to UI Thread by default and all other threads do not have context added by default. Is that correct?
|
2

Both examples are performing unnecessary work. The best implementation of the method would be:

protected void OnResume() 
{
    DoWorkAsync();
}

In the first case you're forcing a continuation to run in the current context but that continuation has nothing to actually do; it's just pointlessly adding a post to the synchronization context.

The second snippet is adding two pointless posts two the current synchronization context, one explicitly, and one implicitly.

Both methods also have async methods that are adding state machines, even though you don't actually leverage any of that functionality, so that overhead is all entirely wasted.

5 Comments

The first example and your code differ in how exceptions from DoWorkAsync are treated.
@StephenCleary The comment in the code indicates that DoWorkAsync never throws; it handles all of its own exceptions internally.
Hi @Servy, sorry for the misleading. Actually I do need make sure DoOtherWorkAsync() is called after DoWorkAsync() is finished.
@macio.Jun Then making the method async isn't pointless. Posting to the synchronization context you're already in to invoke the same async method still would be.
Thanks @Servy. The second snippet does unnecessarily force DoWorkAsync to be called on UI Thread although OnResume is already on the UI Thread. But without SynchronizationContext.Current.Post then I have to use the first snippet to call async methods.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.