Support async methods in Screen, IActivate etc
See original GitHub issueYou can override Screen
s 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:
- Created 8 years ago
- Reactions:4
- Comments:37 (20 by maintainers)
Top GitHub Comments
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 firstawait
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:
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 👯♂️ 👯
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
andAsyncScreen
, but not also forcing people to use async when they don’t need to.The
wontfix
above was simply about having theIsActive
flag set to true beforeOnActivate
is called.