question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support async methods in Screen, IActivate etc

See original GitHub issue

You can override Screens OnInitialize() with the async keyword and use await within. By design of async-await the Activate method of Screen will continue. Therefore, while OnInitialize() is not completed yet, OnActivate() is already executed.

There are quite common cases where you would not like to have OnActivate() to run before OnInitialize() is completed. For that it is necessary to await OnInitialize() and every child task within there should be created with TaskCreationOptions.AttachedToParent (compare child tasks vs. nested tasks).

In your ViewModel inheriting from Screen you could then do:

protected async override Task OnInitialize()
{
    await Task.Factory.StartNew(() =>
    {
        this.configuration.Load(Properties.Settings.Default);
    }, TaskCreationOptions.AttachedToParent);
}

I have checked this with a copy of Screen as ScreenAwaitingInit which implements two things different (origin source from 1.5.2 but adoptable):

async void IActivate.Activate()
{
    if (this.IsActive)
        return;
    bool flag = false;
    if (!this.IsInitialized)
    {
        this.IsInitialized = flag = true;
        await this.OnInitialize();
    }
    this.IsActive = true;
    ScreenAwaitingInit.Log.Info("Activating {0}.", (object)this);
    this.OnActivate();
    this.Activated((object)this, new ActivationEventArgs()
    {
        WasInitialized = flag
    });
}

protected async virtual Task OnInitialize()
{
}

This is to show what my problem is and what I am after.

Maybe it is possible to support both ways in one Screen implementation or you could provide two Screen classes (inheriting most stuff from ScreenBase) either implementing one behaviour. But it would be great. I would even try to contribute a pull request if I would know what type of solution would be preferred.

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:4
  • Comments:37 (20 by maintainers)

github_iconTop GitHub Comments

5reactions
danielmarbachcommented, Oct 21, 2016

I was reviewing the code base today what would be necessary to make it async. Currently the only true async support is available on the action methods by allowing the users to specify action methods which return a task and end with “Async” implemented by @BrunoJuchli in #154.

All other methods need either to be marked async void which has severe implications for the framework since it is a fire & forget operation (code is executed synchronously until the first await statement and then the invocation is done for Caliburn).

Results need to have an async void Execute method as well and the users need to do a lot of internal exception handling in order to properly fire the completed event. For example:

public class AsyncVoidSayHelloResult : IResult
    {
        private CancellationToken token;

        public AsyncVoidSayHelloResult(CancellationToken token)
        {
            this.token = token;
        }
        public async void Execute(CoroutineExecutionContext context)
        {
            try
            {
                await Task.Delay(5000, token);
                Completed(this, new ResultCompletionEventArgs());
            }
            catch (OperationCanceledException)
            {
                Completed(this, new ResultCompletionEventArgs { WasCancelled = true});
            }
            catch (Exception ex)
            {
                Completed(this, new ResultCompletionEventArgs { Error = ex });
            }
        }

        public event EventHandler<ResultCompletionEventArgs> Completed;
    }

if the user accidentally writes ConfigureAwait(false) into the await statements of the result implementation is going to blow up because the Completed event will be raised potentially on a non-sync context aware thread.

The die is cast guys. Async is coming more and more. Multiple OSS frameworks are moving to async only APIs. Those who still haven’t bought into that idea are going down the cumbersome and error-prone path of implementing the sync and the async APIs redundantly and therefore wasting precious development resources. I think caliburn micro could take the lead and do the following

Yes, I know this sounds like a drastic manner. But let’s face it, we have to move on and adapt to the new world. Blocking operations are a thing of the past, and it is simple to build synchronous APIs into asynchronous APIs but extremely hard to build asynchronous APIs into synchronous ones. Some users might shout out and say but what about my platform XYZ. Well to be fair Caliburn.Micro is pretty much feature-complete and those users can stay on the 3.x versions without any pressure to update.

If you are willing to take the leap, I’m willing to help you out. Embrace the async future, it is happening now 👯‍♂️ 👯

5reactions
nigel-sampsoncommented, Mar 29, 2016

Yup, sorry wasn’t clear here.

Fully intend to add support for an async methods, would like to do this in a way that’s not a major breaking change but hard to see how to do that effectively. I’d like to avoid having both Screen and AsyncScreen, but not also forcing people to use async when they don’t need to.

The wontfix above was simply about having the IsActive flag set to true before OnActivate is called.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Async functions | Can I use... Support tables for HTML5 ...
Async functions make it possible to treat functions returning Promise objects as if they were synchronous. Usage % of. all users, all tracked,...
Read more >
Screens, Conductors and Composition
This method is designed with an async pattern, allowing complex logic such ... stage of the screen lifecycle (if it supports it by...
Read more >
Using Asynchronous Methods in ASP.NET 4.5
This tutorial will teach you the basics of building an asynchronous ASP.NET Web Forms application using Visual Studio Express 2012 for Web, ...
Read more >
How to wait for async method to complete?
The most important thing to know about async and await is that await doesn't wait for the associated call to complete. What await...
Read more >
Task asynchronous programming model
Learn when and how to use Task-based async programming, a simplified approach to asynchronous programming in C#.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found