Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call asynchronous method in constructor?

People also ask

Can you call async method in constructor?

The problem arises when you're trying to call such an asynchronous method from a class constructor: you can't use the await keyword inside the constructor. As long as you're only using methods which don't return a value, you can get away with it by just calling them without await, but that's not the right way to do it.

Can we use await in constructor C#?

It's possible to call this in the constructor, but you can't await an expression that referenced it.

Can you have an async constructor JavaScript?

The static async factory function pattern allows us to emulate asynchronous constructors in JavaScript. At the core of this pattern is the indirect invocation of constructor .


The best solution is to acknowledge the asynchronous nature of the download and design for it.

In other words, decide what your application should look like while the data is downloading. Have the page constructor set up that view, and start the download. When the download completes update the page to display the data.

I have a blog post on asynchronous constructors that you may find useful. Also, some MSDN articles; one on asynchronous data-binding (if you're using MVVM) and another on asynchronous best practices (i.e., you should avoid async void).


You can also do just like this:

Task.Run(() => this.FunctionAsync()).Wait();

Note: Be careful about thread blocking!


I'd like to share a pattern that I've been using to solve these kinds of problems. It works rather well I think. Of course, it only works if you have control over what calls the constructor. Example below

public class MyClass
{
    public static async Task<MyClass> Create()
    {
        var myClass = new MyClass();
        await myClass.Initialize();
        return myClass;
    }

    private MyClass()
    {

    }

    private async Task Initialize()
    {
        await Task.Delay(1000); // Do whatever asynchronous work you need to do
    }
}

Basicly what we do is we make the constructor private and make our own public static async method that is responsible for creating an instance of MyClass. By making the constructor private and keeping the static method within the same class we have made sure that noone could "accidently" create an instance of this class without calling the proper initialization methods. All the logic around the creation of the object is still contained within the class (just within a static method).

var myClass1 = new MyClass() // Cannot be done, the constructor is private
var myClass2 = MyClass.Create() // Returns a Task that promises an instance of MyClass once it's finished
var myClass3 = await MyClass.Create() // asynchronously creates and initializes an instance of MyClass

Implemented on the current scenario it would look something like:

public partial class Page2 : PhoneApplicationPage
{
    public static async Task<Page2> Create()
    {
        var page = new Page2();
        await page.getWritings();
        return page;
    }

    List<Writing> writings;

    private Page2()
    {
        InitializeComponent();
    }

    private async Task getWritings()
    {
        string jsonData = await JsonDataManager.GetJsonAsync("1");
        JObject obj = JObject.Parse(jsonData);
        JArray array = (JArray)obj["posts"];

        for (int i = 0; i < array.Count; i++)
        {
            Writing writing = new Writing();
            writing.content = JsonDataManager.JsonParse(array, i, "content");
            writing.date = JsonDataManager.JsonParse(array, i, "date");
            writing.image = JsonDataManager.JsonParse(array, i, "url");
            writing.summary = JsonDataManager.JsonParse(array, i, "excerpt");
            writing.title = JsonDataManager.JsonParse(array, i, "title");

            writings.Add(writing);
        }

        myLongList.ItemsSource = writings;
    }
}

And instead of doing

var page = new Page2();

You would be doing

var page = await Page2.Create();

A quick way to execute some time-consuming operation in any constructor is by creating an action and run them asynchronously.

new Action( async() => await InitializeThingsAsync())();

Running this piece of code will neither block your UI nor leave you with any loose threads. And if you need to update any UI (considering you are not using MVVM approach), you can use the Dispatcher to do so as many have suggested.

A Note: This option only provides you a way to start an execution of a method from the constructor if you don't have any init or onload or navigated overrides. Most likely this will keep on running even after the construction has been completed. Hence the result of this method call may NOT be available in the constructor itself.


Try to replace this:

myLongList.ItemsSource = writings;

with this

Dispatcher.BeginInvoke(() => myLongList.ItemsSource = writings);