Skip to content

Instantly share code, notes, and snippets.

@JakeGinnivan
Created November 10, 2012 08:27
Show Gist options
  • Select an option

  • Save JakeGinnivan/4050418 to your computer and use it in GitHub Desktop.

Select an option

Save JakeGinnivan/4050418 to your computer and use it in GitHub Desktop.
public async void SaveDocument()
{
if (IsWorking) return;
var doc = MDI.ActiveItem as DocumentViewModel;
if (doc != null)
{
using (DoingWork(string.Format("Saving {0}", doc.MarkpadDocument.Title)))
{
await doc.Save();
await TaskEx.Delay(5000);
}
}
}
//If I add this guy, I get a 5 second UI thread lockup... wtf
public bool CanSaveDocument
{
get { return !IsWorking; }
}
@distantcam
Copy link
Copy Markdown

PropertyChanged.Fody is adding a propertychanged event for CanSaveDocument to IsWorking property, so when the SaveDocument sets IsWorking to true it causes CM to refresh the command, but of course it's already running.

The bigger question is, why does CM not block the UI in general? Because even though SaveDocument is async, it's still awaited on the UI thread, which is why it still blocks when you use a DelegateCommand instead of CM.

@JakeGinnivan
Copy link
Copy Markdown
Author

I cant see any reason why CM blocks. This is what should happen:

  • Call SaveDocument
  • DoWork sets IsWorking, Fody raises Property Changed for IsWorking and CanSaveDocument
  • await doc.Save(); yields so UI thread is now free
  • WPF/CM handle PropertyChanged events
  • Because CanSaveDocument raised a changed event, CM and WPF commanding should call CanSaveDocument, which returns false. Button should get disabled
  • doc.Save returns, execution of the SaveDocument state machine continues, hits await TaskEx.Delay(5000), which yields execution again, so UI thread is free
  • State machine continues after 5 seconds, DoingWork is disposed, which sets IsWorking to false, which raises property changed for IsWorking and CanSaveDocument
  • WPF/CM should re-enable the button

If I use an ICommand, so CanSaveDocument is private, it works great. If I make it public, I get the UI thread lockup. Just dont understand why...

@distantcam
Copy link
Copy Markdown

Stop blaming CM! It's not CM that's blocking if you're using a DelegateCommand because CM isn't involved.

Since the issue also occurs when the property is public and you use a delegate command I'd say it's a weird interaction with WPF bindings, INotifyPropertyChanged and async.

@JakeGinnivan
Copy link
Copy Markdown
Author

@distantcam I put the delegate command in to fix the issue. DelegateCommand = working, CM = not

@caleb-vear
Copy link
Copy Markdown

Who sets IsWorking, because the moment that is set is when CM will be handling the event not when you hit the await.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment