What is my mistake in implementing an asynchronous RelayCommand? - c#

I am learning WPF and MVVM at the moment and I faced a problem when i tried to write unit tests for a viewmodel, whose commands invoke async methods. That problem is well-described in this question. That question also has a solution: to write a new Command class with an additional awaitable method that can be awaited in unit tests. But since i use MvvmLight, i decided not to write a new class, but to inherit from the built-in RelayCommand class instead. However, i don't seem to understand how to do it properly. Below is a simplified example that illustrates my problem:
AsyncRelayCommand:
public class AsyncRelayCommand : RelayCommand
{
private readonly Func<Task> _asyncExecute;
public AsyncRelayCommand(Func<Task> asyncExecute)
: base(() => asyncExecute())
{
_asyncExecute = asyncExecute;
}
public AsyncRelayCommand(Func<Task> asyncExecute, Action execute)
: base(execute)
{
_asyncExecute = asyncExecute;
}
public Task ExecuteAsync()
{
return _asyncExecute();
}
//Overriding Execute like this fixes my problem, but the question remains unanswered.
//public override void Execute(object parameter)
//{
// _asyncExecute();
//}
}
My ViewModel (based on the default MvvmLight MainViewModel):
public class MainViewModel : ViewModelBase
{
private string _welcomeTitle = "Welcome!";
public string WelcomeTitle
{
get
{
return _welcomeTitle;
}
set
{
_welcomeTitle = value;
RaisePropertyChanged("WelcomeTitle");
}
}
public AsyncRelayCommand Command { get; private set; }
public MainViewModel(IDataService dataService)
{
Command = new AsyncRelayCommand(CommandExecute); //First variant
Command = new AsyncRelayCommand(CommandExecute, () => CommandExecute()); //Second variant
}
private async Task CommandExecute()
{
WelcomeTitle = "Command in progress";
await Task.Delay(1500);
WelcomeTitle = "Command completed";
}
}
As far as i understand it, both First and Second variants should invoke different constructors, but lead to the same result. However, only the second variant works the way i expect it to. The first one behaves strangely, for example, if i press the button, that is binded to Command once, it works ok, but if i try to press it a second time a few seconds later, it simply does nothing.
My understanding of async and await is far from complete. Please explain me why the two variants of instantiating the Command property behave so differently.
P.S.: this behavior is noticeable only when i inherit from RelayCommand. A newly created class that implements ICommand and has the same two constructors works as expected.

OK, I think I found the problem. RelayCommand uses a WeakAction to allow the owner (target) of the Action to be garbage collected. I'm not sure why they made this design decision.
So, in the working example where the () => CommandExecute() is in the view model constructor, the compiler is generating a private method on your constructor that looks like this:
[CompilerGenerated]
private void <.ctor>b__0()
{
this.CommandExecute();
}
Which works fine because the view model is not eligible for garbage collection.
However, in the odd-behavior example where the () => asyncExecute() is in the constructor, the lambda closes over the asyncExecute variable, causing a separate type to be created for that closure:
[CompilerGenerated]
private sealed class <>c__DisplayClass2
{
public Func<Task> asyncExecute;
public void <.ctor>b__0()
{
this.asyncExecute();
}
}
This time, the actual target of the Action is an instance of <>c__DisplayClass2, which is never saved anywhere. Since WeakAction only saves a weak reference, the instance of that type is eligible for garbage collection, and that's why it stops working.
If this analysis is correct, then you should always either pass a local method to RelayCommand (i.e., do not create lambda closures), or capture a (strong) reference to the resulting Action yourself:
private readonly Func<Task> _asyncExecute;
private readonly Action _execute;
public AsyncRelayCommand(Func<Task> asyncExecute)
: this(asyncExecute, () => asyncExecute())
{
}
private AsyncRelayCommand(Func<Task> asyncExecute, Action execute)
: base(execute)
{
_asyncExecute = asyncExecute;
_execute = execute;
}
Note that this actually has nothing to do with async; it's purely a question of lambda closures. I suspect it's the same underlying issue as this one regarding lambda closures with Messenger.

Related

RelayCommand from lambda with constructor parameters

If, in a XAML file, I bind a Button to "Command" from the following class, then clicking the Button does not cause DoIt to be executed:
class Thing()
{
public Thing(Foo p1)
{
Command = new RelayCommand(() => DoIt(p1));
}
private DoIt(Foo p)
{
p.DoSomething();
}
public ICommand Command { get; private set; }
}
However, it does work if I initialize a field from p1 and pass the field as a parameter to the method call inside the lambda:
class Thing()
{
private Foo field;
public Thing(Foo p1)
{
field = p1;
Command = new RelayCommand(() => DoIt(field));
}
private DoIt(Foo p)
{
p.DoSomething();
}
public ICommand Command { get; private set; }
}
Why does the former fail, but the latter work as expected?
Probably relevant: How do closures work behind the scenes? (C#)
EDIT: To clarify, the following would also work for me. However, I would still like to know why the second example did what I expected, but the first one did not.
class Thing()
{
private Foo field;
public Thing(Foo p1)
{
field = p1;
Command = new RelayCommand(DoIt);
//Command = new RelayCommand(() => DoIt()); Equivalent?
}
private DoIt()
{
field.DoSomething();
}
public ICommand Command { get; private set; }
}
It's an old question but I recently stumbled upon this topic and it's worth answering.
The reason for this strange behavior originates from the MVVM Light implementation of RelayCommand. The execute and canexecute handlers are stored as WeakAction _execute and WeakFunc<bool> _canExecute in the relay command. The WeakAction is an attempt to allow the GC cleanup of viewmodels when the command is still referenced by the UI for some reason.
Skipping some details, the bottom line is: assigning a viewmodel method as handler works great, because the WeakAction will stay alive as long as the viewmodel stays alive. For a dynamically created Action, the situation is different. If the only reference to that action is inside the RelayCommand, only a weak reference exists and GC can collect the action at any time, turning the whole RelayCommand into a dead brick.
Ok, time for the details. The implementation of WeakAction is not blindly storing a weak reference to the action - this would lead to many disappearing references. Instead, a combination of a weak Delegate.Target reference and an Delegate.MethodInfo is stored. For a static method, the method will be stored by strong reference.
Now, this leads to three categories of lambda:
static method: () => I_dont_access_anything_nonstatic() will be stored as a strong reference
closure on member variables: () => DoIt(field) the closure method will be created in the viewmodel class, the action target is the viewmodel and will stay alive as long as the viewmodel stays alive.
closure on local variables: () => DoIt(p1) the closure will create a separate class instance to store the captured variables. This separate instance will be the action target and there won't be any strong reference to it - GC cleans up at some point
Important: as far as I can tell, this behavior might change with Roslyn: Delegate caching behavior changes in Roslyn so there is a chance that todays working code with case (2) turns into non-working code with Roslyn. However, I didn't test this assumption, it might work out completely different.
your Problem is that calling the Method DoIt is inside another anonymous Method created by the lamda expression. Your expression
() => DoIt(p1);
creates a anonymous Method without parameters (seen as there are no variables provided in the first braces).
I would recommend you to use the generic constructor from mvvm-light for creating the Command:
class Thing
{
public Thing()
{
Command = new GalaSoft.MvvmLight.Command.RelayCommand<bool>(DoIt);
}
private void DoIt(bool p)
{
p.DoSomething(p);
}
public System.Windows.Input.ICommand Command { get; private set; }
}
Then just bind the Button to the "Command".

RelayCommand best practice

I'm working with RelayCommands (they are in a separate class) for about a month now and I got the feeling they're kind of clunky when declaring them. Below I have 3 ways I can think of how I can declare a RelayCommand.
In a first case I declare my ICommand and then when the ViewModel is loading I construct my RelayCommand that points to a method in my code.
public class MyViewModel
{
public ICommand MyCommand { get; private set; }
public MyViewModel()
{
MyCommand = new RelayCommand(MyMethod, CanMyMethod);
}
private void MyMethod()
{
// Do something here ...
}
private bool CanMyMethod()
{
return string.IsNullOrEmpty(MyString) ? false : true;
}
}
A second method is to do everything at once.
public ICommand MyCommand
{
get
{
return new RelayCommand(
() =>
{
// Do something here ...
},
() =>
string.IsNullOrEmpty(MyString) ? false : true);
}
}
Now, I'm planning to write an application with quite some Commands in a certain ViewModel. I also can't split the ViewModel in smaller ViewModels because all the controls have to work together.
So my questions are:
What is the best approach to declaring and constructing ICommands? Is it one of my approaches or is there an easier way?
How hard is it to maintain the overview with each approach considering there are over 50 ICommands in a single ViewModel.
I'm hoping to release my application on both Windows 7, 8 and 10 in the future. Are there any limitations to RelayCommands I have to take in account if I'm only using .NET4.5?
Besides RelayCommands I also found this project: Caliburn-Micro. It allows you to do something like the code below. Does anyone have an idea how good this works performance wise in comparison to RelayCommands? This is just an extra question and not required to be answered to have a post marked as an answer.
Xaml (View)
<Button x:Name="Login" Content="Log in" />
ViewModel
public bool CanLogin(string username, string password)
{
return !String.IsNullOrEmpty(username) && !String.IsNullOrEmpty(password);
}
public string Login(string username, string password)
{
...
}
Refer below answers.
What is the best approach to declaring and constructing ICommands?
Is it one of my approaches or is there an easier way? Ans:You can
take combined approach. If your execute method is very minimal, you
can use RelayCommnd otherwise you can implement your own ICommand in
a separate class. This will improve readability of your viewmodel as
well as modularity of your code.
How hard is it to maintain the overview with each approach considering there are over 50 ICommands in a single ViewModel.
Ans: Cover in Ans 1
I'm hoping to release my application on both Windows 7, 8 and 10 in the future. Are there any limitations to RelayCommands I have to take in account if I'm only using .NET4.5?
Ans: I am not seeing any limitation in Windows 7 or 8 but not sure about Windows 10.
Besides RelayCommands I also found this project: Caliburn-Micro. It allows you to do something like the code below. Does anyone have an idea how good this works performance wise in comparison to RelayCommands? This is just an extra question and not required to be answered to have a post marked as an answer.
Ans: I am not sure about source code of RelayCommands in Caliburn-Micro. But if it using CommandManager to achieve the CanExecute functionality. Then command manager will get triggered for all the user inputs change and hence that will cause performance issues if have some heavy logic in the CanExecute method. Refer Are there any performance implications with CanExecuteCommand?
Here's the pattern that I prefer, which is basically a variation of method 1:
public class MyViewModel
{
private readonly RelayCommand myCommand;
public MyViewModel()
{
this.myCommand = new RelayCommand(this.DoStuff, () => ...);
}
public ICommand MyCommand
{
get { return this.myCommand; }
}
private void DoStuff() { ... }
}
This has the advantage of keeping extra methods on your RelayCommand implementation (like RaiseCanExecuteChanged) around for use from your view model, but exposes only an ICommand instance to consumers.
I agree with Krowi, the first approach is much easier to read. But I would put your relay command into its own class so you can re-use it:
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion
}

Avoid instantiate object when every time constructor being called

I have a PersonViewModel class and bind with Person User Control. Everytime when I select Person Use Control page, createPersonCommand, deletePersonCommand, viewPersonCommand will always reinstantiate. Are there any ideas to create those command once ? Execpt for InitializePersonCollection method because will retrieve latest date from DB.
My senior comments on my assignment, and he was mentioned on this.
private ICommand createPersonCommand;
public ICommand CreatePersonCommand
{
get { return createPersonCommand; }
}
private ICommand deletePersonCommand;
public ICommand DeletePersonCommand
{
get { return deletePersonCommand; }
}
private ICommand viewPersonCommand;
public ICommand ViewPersonCommand
{
get { return viewPersonCommand; }
}
public PersonViewModel()
{
createPersonCommand = new DelegateCommand<object>(ExecuteCreatePersonCommand);
deletePersonCommand = new DelegateCommand<object>(ExecuteDeletePersonCommand);
viewPersonCommand = new DelegateCommand<object>(ExecuteViewPersonCommand);
InitializePersonCollection();
}
As long as the command executing methods are not static, you will need to do this. If for whatever reason you can make the command methods static, you could make your DelegateCommands static as well and only assign the static instances to your members.
But as people already mentioned, that would not make sense. The code you have is a well established pattern. There is no reason to change it.
Maybe you should check if the commands are actually well placed. Does every person need it's own command, or do you need commands in your main viewmodel that get a single person as parameter? That might make more sense.
You can use "lazy-loading". Then commands will be instantiated on-demand and will not affect speed of loading data from database.
private ICommand createPersonCommand;
public ICommand CreatePersonCommand
{
get {
if (createPersonCommand == null) {
createPersonCommand = new DelegateCommand<object>(ExecuteCreatePersonCommand)
}
return createPersonCommand;
}
}

Subscribing to EF changes with RX

I'm probably totally misunderstanding what RX is all about, but I thought it would be a neat way of allowing various client applications in my code to subscribe to notifications of changes to certain Entity Framework Code First types.
So in my UOW Commit methood I have
var changes = DbContext.ChangeTracker.Entries<EntEvent>().Where(ee => ee.State != EntityState.Unchanged);
Hub.Instance.NotifyBeforeSave(changes);
and my (rather basic) hub class looks like this...
public sealed class Hub
{
private static readonly Hub instance = new Hub();
static Hub(){}
private Hub(){}
public static Hub Instance
{
get { return instance; }
}
public IObservable<System.Data.Entity.Infrastructure.DbEntityEntry<EntEvent>> BeforeSave = new Subject<DbEntityEntry<EntEvent>>();
public void NotifyBeforeSave<T>(IEnumerable<System.Data.Entity.Infrastructure.DbEntityEntry<T>> changes) where T:class
{
var x = changes.Where(c => typeof(T) == typeof(EntEvent)) as IEnumerable<System.Data.Entity.Infrastructure.DbEntityEntry<EntEvent>>;
BeforeSave = x.ToObservable();
}
}
and then I thought I could subscribe a client (observer) by creating an instance of the following and calling attach.
public class SampleConsumer : IObserver<DbEntityEntry<EntEvent>>
{
public void attach()
{
Hub.Instance.BeforeSave.Subscribe(this);
}
public void OnNext(DbEntityEntry<EntEvent> value)
{
var x = value;
}
public void OnError(Exception error)
{
var y = error;
}
public void OnCompleted()
{
}
}
but breakpoints in OnNext and OnError never get called.
I'm probably 180deg away from where I should be, but we have to start somewhere!
The problem is that you don't have an asynchronous source.
DbContext.ChangeTracker.Entries<EntEvent>()
is a collection. You can convert it to an observable using
IEnumerble.ToObservable();
but that does not make it asynchronous. In fact, it will enumerate the collection right away upon subscription. If the collection happens to be empty, it will do nothing at all. Google the difference between cold/hot observables to understand.
You need an asynchronous source, something like an event.
I don't know EF very well, my guess is that the
((IObjectContextAdapter)DbContext).ObjectContext.SavingChanges
event might be what you need.
Good luck!
Plug in Nick's
https://github.com/NickStrupat/EntityFramework.Triggers
https://github.com/NickStrupat/EntityFramework.Rx
He has patterns with and without deriving from his context, that permit:
DbObservable<Context>.FromInserted<Person>();

How to cancel a deeply nested process

I have a class that is a "manager" sort of class. One of it's functions is to signal that the long running process of the class should shut down. It does this by setting a boolean called "IsStopping" in class.
public class Foo
{
bool isStoping
void DoWork() {
while (!isStopping)
{
// do work...
}
}
}
Now, DoWork() was a gigantic function, and I decided to refactor it out and as part of the process broke some of it into other classes. The problem is, Some of these classes also have long running functions that need to check if isStopping is true.
public class Foo
{
bool isStoping
void DoWork() {
while (!isStopping)
{
MoreWork mw = new MoreWork()
mw.DoMoreWork() // possibly long running
// do work...
}
}
}
What are my options here?
I have considered passing isStopping by reference, which I don't really like because it requires there to be an outside object. I would prefer to make the additional classes as stand alone and dependancy free as possible.
I have also considered making isStopping a property, and then then having it call an event that the inner classes could be subscribed to, but this seems overly complex.
Another option was to create a "Process Cancelation Token" class, similar to what .net 4 Tasks use, then that token be passed to those classes.
How have you handled this situation?
EDIT:
Also consider that MoreWork might have a EvenMoreWork object that it instantiates and calls a potentially long running method on... and so on. I guess what i'm looking for is a way to be able to signal an arbitrary number of objects down a call tree to tell them to stop what they're doing and clean up and return.
EDIT2:
Thanks for the responses so far. Seems like there's no real consensus on methods to use, and everyone has a different opinion. Seems like this should be a design pattern...
You can go two ways here:
1) The solution you've already outlined: pass a signaling mechanism to your subordinate objects: a bool (by ref), the parent object itself cloaked in an interface (Foo: IController in the example below), or something else. The child objects check the signal as needed.
// Either in the MoreWork constructor
public MoreWork(IController controller) {
this.controller = controller;
}
// Or in DoMoreWork, depending on your preferences
public void DoMoreWork(IController controller) {
do {
// More work here
} while (!controller.IsStopping);
}
2) Turn it around and use the observer pattern - which will let you decouple your subordinate objects from the parent. If I were doing it by hand (instead of using events), I'd modify my subordinate classes to implement an IStoppable interface, and make my manager class tell them when to stop:
public interface IStoppable {
void Stop();
}
public class MoreWork: IStoppable {
bool isStopping = false;
public void Stop() { isStopping = true; }
public void DoMoreWork() {
do {
// More work here
} while (!isStopping);
}
}
Foo maintains a list of its stoppables and in its own stop method, stops them all:
public void Stop() {
this.isStopping = true;
foreach(IStoppable stoppable in stoppables) {
stoppable.Stop();
}
}
I think firing an event that your subclasses subscribe to makes sense.
You could create a Cancel() method on your manager class, and on each of your other worker classes. Base it on an interface.
The manager class, or classes that instantiate other worker classes, would have to propagate the Cancel() call to the objects they are composed of.
The deepest nested classes would then just set an internal _isStopping bool to false and your long-running tasks would check for that.
Alternatively, you could maybe create a context of some sort that all the classes know about and where they can check for a canceled flag.
Another option was to create a
"Process Cancelation Token" class,
similar to what .net 4 Tasks use, then
that token be passed to those classes.
I am not familiar with this, but if it is basically an object with a bool property flag, and that you pass into each class, then this seems like the cleanest way to me. Then you could make an abstract base class that has a constructor that takes this in and sets it to a private member variable. Then your process loops can just check that for cancellation.
Obviously you will have to keep a reference to this object you have passed into your workers so that it's bool flag can be set on it from your UI.
Your nested types could accept a delegate (or expose an event) to check for a cancel condition. Your manager then supplies a delegate to the nested types that checks its own "shouldStop" boolean. This way, the only dependency is of the ManagerType on the NestedType, which you already had anyway.
class NestedType
{
// note: the argument of Predicate<T> is not used,
// you could create a new delegate type that accepts no arguments
// and returns T
public Predicate<bool> ShouldStop = delegate() { return false; };
public void DoWork()
{
while (!this.ShouldStop(false))
{
// do work here
}
}
}
class ManagerType
{
private bool shouldStop = false;
private bool checkShouldStop(bool ignored)
{
return shouldStop;
}
public void ManageStuff()
{
NestedType nestedType = new NestedType();
nestedType.ShouldStop = checkShouldStop;
nestedType.DoWork();
}
}
You could abstract this behavior into an interface if you really wanted to.
interface IStoppable
{
Predicate<bool> ShouldStop;
}
Also, rather than just check a boolean, you could have the "stop" mechanism be throwing an exception. In the manager's checkShouldStop method, it could simply throw an OperationCanceledException:
class NestedType
{
public MethodInvoker Stop = delegate() { };
public void DoWork()
{
while (true)
{
Stop();
// do work here
}
}
}
class ManagerType
{
private bool shouldStop = false;
private void checkShouldStop()
{
if (this.shouldStop) { throw new OperationCanceledException(); }
}
public void ManageStuff()
{
NestedType nestedType = new NestedType();
nestedType.Stop = checkShouldStop;
nestedType.DoWork();
}
}
I've used this technique before and find it very effective.
Litter your code with statements like this wherever it is most sensible to check the stop flag:
if(isStopping) { throw new OperationCanceledException(); }
Catch OperationCanceledException right at the top level.
There is no real performance penalty for this because (a) it won't happen very often, and (b) when it does happen, it only happens once.
This method also works well in conjunction with a WinForms BackgroundWorker component. The worker will automatically catch a thrown exception in the worker thread and marshal it back to the UI thread. You just have to check the type of the e.Error property, e.g.:
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if(e.Error == null) {
// Finished
} else if(e.Error is OperationCanceledException) {
// Cancelled
} else {
// Genuine error - maybe display some UI?
}
}
You can flatten your call stack by turning each DoWork() call into a command using the Command pattern. At the top level, you maintain a queue of commands to perform (or a stack, depending on how your commands interact with each other). "Calling" a function is translated to enqueuing a new command onto the queue. Then, between processing each command, you can check whether or not to cancel. Like:
void DoWork() {
var commands = new Queue<ICommand>();
commands.Enqueue(new MoreWorkCommand());
while (!isStopping && !commands.IsEmpty)
{
commands.Deque().Perform(commands);
}
}
public class MoreWorkCommand : ICommand {
public void Perform(Queue<ICommand> commands) {
commands.Enqueue(new DoMoreWorkCommand());
}
}
Basically, by turning the low-level callstack into a data structure you control, you have the ability to check stuff between each "call", pause, resume, cancel, etc..

Categories

Resources