1

I have a ListBox, where my SelectedValue is set to a class DefaultStrediska which has IEditableObject implemented. What I am doing every time user selects a new item under this particular ListBox (SelectedValue changes), I first check if any change has been made, and if yes; then I ask user if he wants to save temporary changes (otherwise I discard them and return back to the original values).

I am using Mahapps.Metro async method for displaying a message (rather than using traditional System.Windows.MessageBox) and getting the result. The problem is, that this is an asynchronous method that I have to call from my property. Here it is how I do it:

    private async Task<bool> GetResult()
    {
        if (await Window.ShowMessageAsync("Zmena v údajoch", "Pozor! Nastala zmena v údajoch. Prajete si ich dočasne uložiť zmeny?", MessageDialogStyle.AffirmativeAndNegative) == MessageDialogResult.Affirmative)
            _SelectedStredisko.EndEdit();

    return true;
    }

    private DefaultStrediska _SelectedStredisko;
    public DefaultStrediska SelectedStredisko
    {
        get { return _SelectedStredisko; }
        set
        {
            //check if any changes have been made
            if (value != null && _SelectedStredisko != null)
            {
                if (_SelectedStredisko.WasChangeMade())
                {
                    var x = GetResult().Result;
                }
            }

            _SelectedStredisko = value;

            //create backup of current data
            _SelectedStredisko.BeginEdit();

            OnPropertyChanged("SelectedStredisko");
        }
    }

However the problem is, that now my var x = GetResult().Result completely blocks the UI thread and I neither get the messagebox, nor can do anything else. If I remove .Result, then the code first goes to _SelectedStredisko = value and only afterwards calls the GetResult() method, which is unacceptable.

What am I doing wrong in here?

Robert J.
  • 2,631
  • 8
  • 32
  • 59
  • 2
    Don't use a property setter, create an async method for setting that property. – Lasse V. Karlsen Aug 19 '15 at 11:49
  • Could you please show me how? I am not quite sure how to do it. – Robert J. Aug 19 '15 at 11:50
  • possible duplicate of [How to call an async method from a getter or setter?](http://stackoverflow.com/questions/6602244/how-to-call-an-async-method-from-a-getter-or-setter) – EZI Aug 19 '15 at 11:56
  • I tried one of the answers from the link above: *App.Current.Dispatcher.InvokeAsync(async () =>here is the GetResult() code)*, but reacted the same way as if I removed **.Result**. How come it did not wait when it was marked as async? – Robert J. Aug 19 '15 at 12:11

1 Answers1

0

There are a number of ways to avoid the deadlock, I go through a few of them here. I think in your case it might be best to use ConfigureAwait(false) when you are showing the message, but I haven't used that API myself.

await Window.ShowMessageAsync(..).ConfigureAwait(false)
NeddySpaghetti
  • 13,187
  • 5
  • 32
  • 61