1

In my FolderViewModel, I have

public string FolderPath
        {
            get
            {
                if (folderPath == null)
                {
                    GetFolderPathAsync();
                    return "Loading...";
                }
                return folderPath;
            }
            set
            {
                folderPath = value;
                Changed(nameof(FolderPath));
            }
        }

GetFolderPathAsync is an async method which makes server calls to fetch the path and Sets FolderPath.

Now in another class, I create folderviewmodels and set their paths this way

folderViewModel.FolderPath = parent.FolderPath+"/"+folder.Name;

The problem is get is that, the path ends up getting set to "Loading.../foldername" and never updates when the parent folder's folderpath updates from "loading..." after its been fetched from the server. how can i fix ths? Im not great with threading so i really dont know how to fix this. i was wondering if there is a way i could make the setting of folderPath wait for the GetFolderPathAsync to finish somehow?

thanks for the help!

an007
  • 111
  • 1
  • 9
  • Possible duplicate of [WPF Best practice for async property](https://stackoverflow.com/questions/46584838/wpf-best-practice-for-async-property) – Sinatr Mar 29 '19 at 15:40
  • Properties shouldn't kick off async operations. If you call the `GetFolderPathAsync` method from an async method, you could await it and then set the data-bound property to "loading" once it has completed. This assumes that `GetFolderPathAsync` returns a `Task`. – mm8 Mar 29 '19 at 15:42
  • You can simply add a continuation task to run after `GetFolderPathAsync()` to invoke and rise notification. – Sinatr Mar 29 '19 at 15:42

1 Answers1

0

A property shouldn't kick off an asynchronous operation. That's the main reason why async properties are not supported in C#. Please refer to @Stephen Cleary's blog for more information.

If you instead call the GetFolderPathAsync method from an async method, you could await it and then set the data-bound property to "Loading..." once it has completed. This assumes that GetFolderPathAsync returns a Task or a Task<T>:

public string FolderPath
{
    get
    {
        return folderPath;
    }
    set
    {
        folderPath = value;
        Changed(nameof(FolderPath));
    }
}
...
folderViewModel.FolderPath = parent.FolderPath+"/"+folder.Name;
await folderViewModel.GetFolderPathAsync();
folderViewModel.FolderPath = "Loading...";

The other option would be to use the ContinueWith method to create a continuation that executes asynchronously when the task completes:

if (folderPath == null)
{
    GetFolderPathAsync().ContinueWith(_ => 
    {
        folderPath = "Loading...";
        Changed(nameof(FolderPath));
    });
    return folderPath;
}
mm8
  • 163,881
  • 10
  • 57
  • 88
  • @an007: What part didn't work? Again, it's wrong to call asynchronous methods from the getter of the property so you should rethink your design. – mm8 Apr 04 '19 at 09:32