IPartImportsSatisfiedNotification - INavigationAware

Dec 1, 2012 at 11:27 AM

Hi List,

i just playing around with IPartImportsSatisfiedNotification

What's about this usage:

public async void OnImportsSatisfied()

{

Employees =  await this.employeeService.EmployeLookupListAsync();

}

is there anything against?

The same goes for INavigationAware and:

public  void async OnNavigatedTo(NavigationContext navigationContext)

{

mylist = await DoDatabaseStuff;

}

Is this ok or is there any hidden traps inside?

Thanks

Peter

 

Developer
Dec 3, 2012 at 7:15 PM

Hi Peter,

I am not familiar with the new async / await capabilities provided by .NET 4.5 but I believe there could be problems with the OnNavigatedTo method you are defining. Based on my understanding, when defining an async method with a returning type of void, that method can be used as an event handler that when invoked will execute asynchronously. However, the code that invokes the handler is not able to await for the event handler to finish nor it's able to catch any exceptions throw inside it. As far as I know, Prism's Navigation is not prepared to work with async methods, hence this could case an unexpected behavior in your application. Also, based on this, it seems that Prism will not be able to catch an exception raised inside the OnNavigatedTo method and thus, it might not be able to inform when a navigation request fails.

Based on my understanding, if the method is not declared as async, then it would be able to await for inner asynchronous operations (e.g invoking EmployeLookupListAsync) without returning the control to its invoking method. Hence, the asynchronous operations would be handled inside the methods and Prism could use them as simple synchronous methods, avoiding the problems mentioned before.

You can find more information about this in the following MSDN article:

Regarding the OnImportsSatisfied method, take into account that, as described in MEF's CodePlex site, "OnImportsSatisfied is called when all imports that could be satisfied have been satisfied." Hence, even if the OnImportsSatisfied method is invoked, it does not ensure that all corresponding properties were populated, so it might be a good idea to check if the property is set before acceding it (for example, checking if the employeeService member is null).

You can find more information about this in MEF's CodePlex site:

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Dec 4, 2012 at 7:20 AM
Edited Dec 4, 2012 at 7:24 AM

Hi,

thanks a lot for the answer.

So, what did you think is the best place to run the DB operations. Start them in the constructor seems to be a bad idea as well.

Did you have any sample about this:

<Based on my understanding, if the method is not declared as async, then it would be able to await for inner <asynchronous operations (e.g invoking EmployeLookupListAsync) without returning the control to its invoking <method.

Peter

Developer
Dec 4, 2012 at 6:31 PM

Hi Peter,

Sorry, after further investigation I found that an await expression can only occur in the body of a method or lambda expression that is marked with an async modifier. Hence, what I said about using an await expression inside a synchronous method is wrong. My sincere apologies.

Regarding the topic about where to run database operations, in my opinion it could be possible to run such operations in the OnNavigatedTo method. The problem is that Prism's navigation as out of the box does not support asynchronous operations in the OnNavigatedTo and OnNavigatedFrom methods. Therefore, if you invoke an asynchronous method in the OnNavigatedTo method, the navigation sequence will continue executing without waiting for it to finish and, while in some scenarios this might not represent an issue, in others it could cause an unexpected behavior.

If you want to be able to perform an asynchronous operation inside the OnNavigatedTo and being able to wait for that operation to complete before continuing with the navigation sequence, I believe you could find the approach proposed by a user of the community in the following thread interesting:

Regards,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Dec 4, 2012 at 7:28 PM

Hi,

nothing to apologies.

The link is very usefull and i will try it out.

Let me ask in another way.

 I'm not fixed to use the OnNavigatedTo method if there is  any other recommendation  to start async operations to initialize a viewmodel while using the INavigationAware interface.

Peter

 

Developer
Dec 5, 2012 at 9:07 PM

Hi Peter,

In my opinion, as the problem here seems to be what issues might arise from invoking an async method in the middle of the navigation sequence, how about invoking the async operations after the navigation is completed?

The RegionNavigationService provided by Prism to perform navigation request defines a Navigated event that is raised at the end of the navigation sequence. You could take advantage of this event to be notified when the navigation is finished, this means when your view / view model is already created, injected and activated in the region.

For example, you could do something like this to:

// Common synchronous method.
public void OnNavigatedTo(NavigationContext context)
{
    // We take any data we require from the navigation context and save it 

    // Then we subscribe to the Navigated event with an async method
    context.NavigationService.Navigated += OnNavigationCompleted;
}
Then, when the navigation is finished, this method will be raised and the subscribed async method would be executed. As at this point the navigation is completed, I believe you should be able to perform any async operations you want without needing to worry about how them could impact in the navigation sequence:

public async void OnNavigationCompleted(...)
{
    // The same NavigationService as before (for example, stored in a private member.)
    navigationService.Navigated -= OnNavigationCompleted;
    navigationService = null;
    
    Task<IList<Employee>> task = this.employeeService.EmployeLookupListAsync();

    // Perform some other logic

    Employees = await task;
}

Also, for the opposite case (that is, when using async operations when a view is navigated from) you can wait for the asynchronous operations to finish using the ConfirmNavigationRequest method. You can find more information about this in the following section of the documentation:

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Dec 6, 2012 at 7:57 AM

Hi,

that is exactly what i'm looking for.

thanks a lot

Peter