async/await in MVVM without Void methods - c#

I want to use async/await on my windows phone 8 MVVM project and I'm struggling to find a good way to implement my ICommands using this api.
I've been reading a few articles about the subject and I bumped into this one from MSDN below, which states that I have to avoid async voids since it gets difficult to catch unhandled exceptions:
http://msdn.microsoft.com/en-us/magazine/jj991977.aspx
In another question I asked about the subject, someone also said that I shouldn't use async voids. Unless with events.
But the problem is that all examples I can find on the internet use async voids.
This two articles I found are examples:
http://richnewman.wordpress.com/2012/12/03/tutorial-asynchronous-programming-async-and-await-for-beginners/ and
http://blog.mycupof.net/2012/08/23/mvvm-asyncdelegatecommand-what-asyncawait-can-do-for-uidevelopment/
The last one is an implementation of ICommand using async/await, but it also uses async voids.
I'm trying to come up with a solution for this, so I wrote this implementation of ICommand based on the RelayCommand:
public delegate Task AsyncAction();
public class RelayCommandAsync : ICommand
{
private AsyncAction _handler;
public RelayCommandAsync(AsyncAction handler)
{
_handler = handler;
}
private bool _isEnabled;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
if (value != _isEnabled)
{
_isEnabled = value;
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
}
public bool CanExecute(object parameter)
{
return IsEnabled;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
ExecuteAsync();
}
private Task ExecuteAsync()
{
return _handler();
}
}
And I'm trying to use it like this:
in the constructor:
saveCommand = new RelayCommandAsync(SaveSourceAsync);
then:
private async Task SaveSourceAsync()
{
await Task.Run(() => { Save(); });
}
private void Save()
{
// Slow operation
}
The problem is that I'm not feeling comfortable with this and any other implementation as I don't know which is the best and optimal.
Can anyone give some light on how I should use it, preferably with MVVM?

In the referenced article, I did point out that ICommand.Execute is practically an event handler, so it would be considered an exception from the "avoid async void" guideline:
To summarize this first guideline, you should prefer async Task to async void... The exception to this guideline is asynchronous event handlers, which must return void. This exception includes methods that are logically event handlers even if they’re not literally event handlers (for example, ICommand.Execute implementations).
Regarding your ICommand implementation, it actually introduces a flaw by not using async void: the ICommand.Execute implementation will discard the Task without observing its exceptions. So that implementation will ignore any exceptions raised by the async delegate.
In contrast, the blog post you linked to has an async void ICommand.Execute which awaits the Task, allowing the exception to propagate to the UI synchronization context. Which - in this case - is the desired behavior because it's the same behavior you get when a synchronous ICommand.Execute raises an exception.
If you have the inclination, I'd like you to try out an ICommand or two that I've written for possible future inclusion in my AsyncEx library. The first one is a simple command very similar to the one in the blog you posted. The second one is a much more complete "asynchronous command" implementation including cancellation, progress reporting, and automatic management of CanExecute. I'd appreciate any feedback.

Related

Async void on subscribed Prism methods

I understand you should try not to do async void with the exception of event handlers. Does that exception of event handlers include Prism events? Is my example below ok to do?
Module A's View has a DataGrid and when the user clicks a record it publishes the SelectionChangedEvent, the event is subscribed in Module B and might take a while to complete.
public class ModuleA
{
private ObservableCollection<Company> carCollectionOC = new ObservableCollection<Company>();
private void CarCollection_CurrentChanged(object sender, EventArgs e)
{
Company company = (Company)(sender as ICollectionView).CurrentItem;
this.eventAggregator.GetEvent<SelectionChangedEvent>().Publish(company.Brand);
}
}
Module B subscribes and does async void.
public class ModuleB
{
private ObservableCollection<Vehicle> vehicleOC = new ObservableCollection<Vehicle>();
private VehicleService vehicleService;
public ModuleB(IEventAggregator eventAggregator)
{
this.vehicleService = new VehicleService();
this.eventAggregator.GetEvent<SelectionChangedEvent>()
.Subscribe(this.SubscribedMethod,
ThreadOption.UIThread,
false);
}
private async void SubscribedMethod (string brand)
{
this.vehicleOC = await this.GetData(brand);
}
private List<Vehicle> GetVehicles(string carBrand)
{
Console.WriteLine("finishing GetVehicles");
return this.vehicleService.GetVehicleList(carBrand);
}
private async Task<ObservableCollection<Vehicle>> GetData(string carBrand)
{
vehicleListFromService = await Task.Run(() => this.GetVehicles(carBrand));
this.vehicleOC.Clear();
foreach (var vehicle in vehicleListFromService)
this.vehicleOC.Add(vehicle);
return this.vehicleOC;
}
}
Certainly, even stephen clearly (an authority on this subject as far as i am concerned) says:
To summarize this first guideline, you should prefer async Task to
async void. Async Task methods enable easier error-handling,
composability and testability. The exception to this guideline is
asynchronous event handlers, which must return void. This exception
includes methods that are logically event handlers even if they’re not
literally event handlers (for example, ICommand.Execute
implementations).
https://learn.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming
Personally, I always wrap the contents of an async void method in a try-catch and deal with the exception, regardless of the method's contents. I've written a simple helper class to aid with that.
Does that exception of event handlers include Prism events?
Yes. The subscriber has to be Action, that means void MyHandler() (or async void MyHandler()).

System.Threading.Channels ReadAsync() method is blocking execution

Overview
I am attempting to write an IAsyncEnumerable<T> wrapper around an IObserver<T> interface. At first I used a BufferBlock<T> as the backing data store, but I found out through performance testing and research that it is actually a pretty slow type, so I decided to give the System.Threading.Channels.Channel type a go. I had a similar problem with my BufferBlock implementation as this one but this time I'm not sure how to resolve it.
Problem
My GetAsyncEnumerator() loop gets blocked by the await _channel.Reader.WaitToRead(token) call if my IObserver<T>.OnNext() method hasn't written to the _channel yet. What is the correct way to wait for a value to be available to yield in this context without blocking program execution?
Implementation
public sealed class ObserverAsyncEnumerableWrapper<T> : IAsyncEnumerable<T>,
IObserver<T>, IDisposable
{
private readonly IDisposable _unsubscriber;
private readonly Channel<T> _channel = Channel.CreateUnbounded<T>();
private bool _producerComplete;
public ObserverAsyncEnumerableWrapper(IObservable<T> provider)
{
_unsubscriber = provider.Subscribe(this);
}
public async void OnNext(T value)
{
Log.Logger.Verbose("Adding value to Channel.");
await _channel.Writer.WriteAsync(value);
}
public void OnError(Exception error)
{
_channel.Writer.Complete(error);
}
public void OnCompleted()
{
_producerComplete = true;
}
public async IAsyncEnumerator<T> GetAsyncEnumerator(
[EnumeratorCancellation] CancellationToken token = new CancellationToken())
{
Log.Logger.Verbose("Starting async iteration...");
while (await _channel.Reader.WaitToReadAsync(token) || !_producerComplete)
{
Log.Logger.Verbose("Reading...");
while (_channel.Reader.TryRead(out var item))
{
Log.Logger.Verbose("Yielding item.");
yield return item;
}
Log.Logger.Verbose("Awaiting more items.");
}
Log.Logger.Verbose("Iteration Complete.");
_channel.Writer.Complete();
}
public void Dispose()
{
_channel.Writer.Complete();
_unsubscriber?.Dispose();
}
}
Additional Context
It shouldn't matter, but at runtime the IObservable<T> instance passed into the constructor is a CimAsyncResult returned from async calls made to the Microsoft.Management.Infrastructure apis. Those make use of the Observer design pattern which I'm trying to wrap with the fancy new async enumeration pattern.
Edit
Updated with logging to the debugger output and made my OnNext() method async/await as one commenter suggested. You can see it never enters the while() loop.
Further up the call stack I was calling the async method syncronously via the GetAwaiter().GetResult() methods.
Yup, that's a problem.
I did this because in once case I wanted to get the data from within a constructor. I changed that implementation to execute the call using Task.Run() and now the iterators run flawlessly with both implementations.
There are better solutions than blocking on asynchronous code. Using Task.Run is one way to avoid the deadlock, but you still end up with a sub-par user experience (I'm assuming yours is a UI application, since there is a SynchronizationContext).
If the asynchronous enumerator is used to load data for display, then a more proper solution is to (synchronously) initialize the UI to a "Loading..." state, and then update that state as the data is loaded asynchronously. If the asynchronous enumerator is used for something else, you may find some appropriate alternative patterns in my async constructors blog post.

How to call async method from PropertyChanged?

I have an WPF application based on MVVM architecture. I am implementing the common and widely used INotifyPropertyChanged interface on my ViewModels, because I need to react on user interaction.
But how do I perform an asynchronous action (e.g. loading some data) from within the synchronous PropertyChanged event handler without using async void 'hacks'?
Thanks in advance!
EDIT
The main reason why i need to avoid async void is because I am working in an test driven environment. Async void methods are not testable :(
Actually, this is not about async void.
Usually you want to fire async operation and let your property setter return.
Sample snippet:
private string carManufacturerFilter;
public string СarManufacturerFilter
{
get { return carManufacturerFilter; }
set
{
if (carManufacturerFilter != value)
{
carManufacturerFilter = value;
OnPropertyChanged();
// fire async operation and forget about it here;
// you don't need it to complete right now;
var _ = RefreshCarsListAsync();
}
}
}
private async Task RefreshCarsListAsync()
{
// call some data service
var cars = await someDataService.GetCarsAsync(carManufacturerFilter)
.ConfigureAwait(false);
// ...
}
Note, that there are a lot of things to add here:
since this is fire-and-forget approach, you need to block user input until operation is running. In other words, there should be some sort of busy indicator;
you may want to delay async operation firing. This is usually applicable, when there are string properties. You don't want to fire async operation after each char typed by user. Instead it's desirable to wait user to complete input;
there could be several properties, which fire the same async operation (imagine complex data filter). Some of them should fire operation immediately (e.g. checkbox), some of them need delay before firing;
you need to handle exceptions inside async method and display errors somehow.
P.S. I strongly recommend you to take a look at Reactive UI.
The reason async void is supported is to allow using await in event handlers, which are usually void.
If you want it to be testable, write the entire code in another async Task method and have the event handler call it directly. Test this method in your tests.
void OnPropertyChanged(PropertyChangedEventArgs e)
{
OnPropertyChangedAsync(e)
}
// Test this method
async Task OnPropertyChangedAsync(PropertyChangedEventArgs e)
{
...
}
Little late to the party but I'd say this. First, notice that INotifyPropertyChanged says that your view model will implement
public event PropertyChangedEventHandler? PropertyChanged;
Secondly, if you inspect PropertyChangedEventHandler, you'll see that it's a delegate, of course:
public delegate void PropertyChangedEventHandler(object? sender, PropertyChangedEventArgs e);
So why not implement your own delegate using Func<>? For example, if you're looking to stick with the (object? sender, PropertyChangedEventArgs e) parameter pattern that PropertyChanged uses, then I would implement something like
public Func<object?, PropertyChangedEventArgs, Task>? PropertyChangedAsync { get; set; }
in the same place (or in place of) public event PropertyChangedEventHandler? PropertyChanged;.
From there you can "wire it up" just as you would PropertyChanged:
ViewModel.PropertyChanged += OnViewModelPropertyChanged;
ViewModel.PropertyChangedAsync += OnViewModelPropertyChangedAsync;
private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// Do something (synchronously) with the notification
}
private Task OnViewModelPropertyChangedAsync(object? sender, PropertyChangedEventArgs e)
{
// Do something (asynchronously) with the notification
return Task.CompletedTask;
}
By the way, if you really want to get fancy, you could also create a custom PropertyChangedEventHandler event with an interface very similar to INotifyPropertyChanged. Obviously, the only difference is you'd want to return Task or Task<T> instead of void. The solution that I mentioned above using Func<object?, PropertyChangedEventArgs, Task> is just a lot more concise (one line).
You can't. INotifyPropertyChanged doesn't support async calls. You need to do a hack, or rethink you strategy.
INotifyPropertyChanged is not intended for async actions. Its goal is to enable a class notify the UI that its data has changed. The UI works in a dedicated thread, so cross-thread operations must be avoided.
You should use the "dreaded" async void approach.
You can also use Dispatcher.BeingInvoke (async () => { … await …} ), but it will be the same as using async void.

How to implement async INotifyPropertyChanged

I have a class with properties that are bound to my view. To keep my view up-to-date, I implement INotifyPropertyChanged and raise the event everytime some property changes.
Now I got some heavy functions that freeze my application. I want to put them into a background task.
First: here my current approach
(e.g. on button click)
private async void HeavyFunc()
{
foreach (var stuff)
{
count += await Task.Run(() => stuff.Fetch());
}
if (count == 0)
//...
}
stuff class
public async Task<int> Fetch()
{
//network stuff
RaisePropertyChanged("MyProperty");
}
public async void RaisePropertyChanged(string pChangedProperty)
{
await Application.Current.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new ThreadStart(() =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pChangedProperty);
}
);
}
The code above gives an exception ("DependencySource" must be created in the same thread like "DependencyObject").
AFAIK, you generally need to create a new thread and run it (while awaiting it). ´await Task.Run(...);´ should do this job.
Since the PropertyChanged event directly influences the UI, calling it in the UI thread seems to be a good decision. This is why I call Dispatcher.BeginInvoke.
What I don't understand: the exception above is caused when different threads are responsible for the data. But I explicitely calling the event on my UI-thread and the object should be created by the UI-thread too. So why do I get an exception?
My main question is: How do I implement the events for the INotifyPropertyChanged interface generally to avoid or handle most of the async programming problems like above? What should be considered while constructing the functions?
Now I got some heavy functions that freeze my application.
If you're really doing asynchronous "network stuff", then it shouldn't be freezing the app.
My main question is: How do I implement the events for the INotifyPropertyChanged interface generally to avoid or handle most of the async programming problems like above?
The approach that I prefer is to not handle this in the event raising code. Instead, structure the rest of your code so that it respects the UI layer.
In other words, divide your "service" (or "business logic") code from your "UI" code so that it works like this:
// In StuffService class:
public async Task<Result> FetchAsync()
{
//network stuff
return result;
}
// In StuffViewModel class:
public async void ButtonClicked()
{
foreach (var stuff)
{
var result = await Task.Run(() => _stuffService.FetchAsync());
MyProperty = result.MyProperty;
count += result.Count;
}
if (count == 0)
//...
}
public Property MyProperty
{
get { return _myProperty; }
set
{
_myProperty = value;
RaisePropertyChanged();
}
}
private void RaisePropertyChanged([CallerMemberName] string pChangedProperty = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pChangedProperty));
}
This way, there's no manual thread jumping, all properties have the standard ViewModel implementation, the code is simpler and more maintainable, etc.
I did leave in the call to Task.Run, although this should be superfluous if your network calls are truly asynchronous.

Command pattern and asynchronous operations handling in C#

I'd like to hear opinions on the best way to handle asynchronous operations with the Command pattern. Say we have the following example:
public class MyCommand
{
// Sets up receiver and does whatever stuff
public void Execute()
{
_myReceiver.DoSomething();
}
}
The problem is: MyCommand doesn't know whether MyReceiver.DoSomething() has async portions of code. If i wanted to push MyCommand into an undo stack after its execution, i couldn't guarantee that its receiver action has been fully executed, making it uncertain to know if MyCommand reached a state where undoing is possible or not.
I personally thought on the following solution:
Implement some sort of state control in Command
Include "BeginExecute" and "EndExecute" in Command
Include events in MyReceiver and make Command subscribe to them (that seems smelly to me)
To wrap things up, MyCommand would turn into:
public class MyCommand
{
public MyCommand(MyReceiver receiver)
{
_myReceiver = receiver;
_myReceiver.DoSomethingFinished += () => this.EndExecute();
}
public void BeginExecute()
{
this.EnterExecutionState();
_myReceiver.DoSomething();
}
public void EndExecute()
{
this.LeaveExecutionState();
}
// State handling related stuff
}
I now have the means to make sure the Command's receiver has finished executing whatever action and it's ready to be pushed into the undo stack. However, to event-spam every single Receiver class that contains async operations really bugs me.
I haven't found much about this topic in the Internet and would love to hear different approaches.
OBS: Make the Command manage all the asynchronous-related code isn't an option :).
I think you've got way too much going on in a single class. I would break it down like this:
// An immutable command, to be handled in-process.
// ICommand is a marker interface with no members.
public class DoSomething : ICommand
{
public readonly Id;
public DoSomething(Guid id)
{
Id = id;
}
}
// To be handled out-of-process.
[AsynchronousCommand]
public class DoSomethingThatTakesAReallyLongTime : ICommand
{
public readonly Id;
public DoSomethingThatTakesAReallyLongTime(Guid id)
{
Id = id;
}
}
// This guy could take any number of dependencies: ISomethingRepository, DbContext, etc.
// Doesn't matter, but it's probably gonna have dependencies.
public class DoSomethingHandler : IHandler<DoSomething>
{
public void Handle(DoSomething command) // IHandler<T>'s only member
{
// CRUD or call call a domain method
}
}
public class CommandService : ICommandService
{
public void Execute(params ICommand[] commands) // ICommandService's only member
{
foreach(var command in commands)
{
var handler = GetHandler(command); // Could use your IOC container.
if (HasAsyncAttribute())
new Action(() => handler.Handle(command)).BeginInvoke(null, null);
else
handler.Handle(command);
}
}
}
// Something that might consume these
public class SomethingController
{
private readonly ICommandService _commandService;
public SomethingController(ICommandService commandService)
{
_commandService = commandService;
}
[HttpPost]
public void DoSomething(Guid id)
{
_commandService.Execute(new DoSomething(id));
}
[HttpPost]
public void DoSomethingThatTakesAReallyLongTime(Guid id)
{
_commandService.Execute(new DoSomethingThatTakesAReallyLongTime(id));
}
}
The big advantage here is that you can distribute your commands to clients without explicitly dragging along all the dependencies that go with the handlers. The handlers should not be known to the client. All the client needs to know is that it sent a command, and all commands should be assumed to succeed.
Something like this?
public interface ICommand
{
void Execute();
event EventHandler Finished;
}
public class MyCommand : ICommand
{
public MyCommand(MyReceiver receiver)
{
_myReceiver = receiver;
_myReceiver.DoSomethingFinished += () => Finished(); // dont forget null check here.
}
public void Execute()
{
_myReceiver.DoSomething();
}
public event EventHandler Finished;
}
This way, user of this command can register to Finished event so it knows when command has finished its async behaviour and can act acordingly.
Or if you dont wan't to use event, then what about callback?
public class MyCommand : ICommand
{
public MyCommand(MyReceiver receiver)
{
_myReceiver = receiver;
}
public void Execute()
{
_myReceiver.DoSomething(() => Finished()); // dont forget null check here.
}
public event EventHandler Finished;
}
Either way, there simply need to be a way for MyReciever to notify its caller, that it finished. There is no way to bypass it.
First I would add to the name of the method Async to esplicitly signal to your Command class consumer that method executes in async way.
Second, I would add like parameter an Action<T> which will be called as method async call completes. So this method caller can be notified when async sction was terminated.
Edit
obj.DoSomethingAsync(... params, Action<T> onComplete)
If you are going to impose the requirement that all processing is completed before control returns to your Execute method, without modifying the calling code's behavior, you could modify the way that your actions execute.
First initialize all your asynchronous calls and block(wait) on the current thread for calls to return. I'm not sure what the nature of your asynchronous calls are, as in if they are in a Thread that you are aware of, or will be returned on an arbitrary thread, but you should be able to come up with some kind of thread synchronization for your problem.
Try using a Semaphore to block current thread(after calling your async methods), and release the semaphore when all your async methods have returned their response(s). This will have the effect of "re-synchronizing" your async calls.
You can use another synchronization method, but a Semaphore is simple enough to understand.

Categories