463

I have a project where I'm trying to populate some data in a constructor:

public class ViewModel
{
    public ObservableCollection<TData> Data { get; set; }

    async public ViewModel()
    {
        Data = await GetDataTask();
    }

    public Task<ObservableCollection<TData>> GetDataTask()
    {
        Task<ObservableCollection<TData>> task;

        //Create a task which represents getting the data
        return task;
    }
}

Unfortunately, I'm getting an error:

The modifier async is not valid for this item

Of course, if I wrap in a standard method and call that from the constructor:

public async void Foo()
{
    Data = await GetDataTask();
}

it works fine. Likewise, if I use the old inside-out way

GetData().ContinueWith(t => Data = t.Result);

That works too. I was just wondering why we can't call await from within a constructor directly. There are probably lots of (even obvious) edge cases and reasons against it, I just can't think of any. I've also search around for an explanation, but can't seem to find any.

Marty Neal
  • 8,741
  • 3
  • 33
  • 38
  • 11
    No, but in his [blog](http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html), [Stephen Cleary](http://stackoverflow.com/users/263693/stephen-cleary) offers a **factory method** approach as well as others to consider. – DavidRR May 26 '16 at 13:07
  • 1
    The pattern proposed in [this answer](https://stackoverflow.com/a/31471915/398630) works pretty well, it's an offshoot of the factory pattern, but I'm going to start referring to it, specifically, as the `async constructor pattern`. – BrainSlugs83 Aug 14 '18 at 20:13
  • 3
    Please bump this language request: https://github.com/dotnet/csharplang/discussions/419 - the amount of boilerplate code everyone needs to write to have a fully initialized async object is crazy and completely opposite of the trend in C# (less boilerplate). – Dirk Boer Jul 22 '22 at 14:40
  • *" if I wrap in a standard method and call that from the constructor .. it works fine."* Actually, it doesn't. You'll see a warning on the call, due to missing `await`. DO NOT IGNORE such a warning; it can lead to deadlock; your UI can freeze forever. – ToolmakerSteve Jan 26 '23 at 21:00

16 Answers16

496

Since it is not possible to make an async constructor, I use a static async method that returns a class instance created by a private constructor. This is not elegant but it works ok.

public class ViewModel       
{       
    public ObservableCollection<TData> Data { get; set; }       

    //static async method that behave like a constructor       
    async public static Task<ViewModel> BuildViewModelAsync()  
    {       
        ObservableCollection<TData> tmpData = await GetDataTask();  
        return new ViewModel(tmpData);
    }       

    // private constructor called by the async method
    private ViewModel(ObservableCollection<TData> Data)
    {
        this.Data = Data;   
    }
}  
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Pierre Poliakoff
  • 5,305
  • 1
  • 15
  • 4
  • 47
    This answer should have much more votes in my opinion. It gives an answer that encapsulates and hides away the need to call an Initialize() method after an item is constructed, thus preventing the potential bug of constructing an object and forgetting to cal its initialize method. – Robert Oschler Nov 13 '15 at 16:55
  • 2
    Ag, this would be a great solution if you had control over the constructor but if your class implements an abstract base class, e.g. public class LoginModelValidator : AbstractValidator you have a problem – Damian Green Dec 04 '15 at 11:17
  • 19
    This approach uses a [factory pattern](http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html). See another well-written similar answer [here](http://stackoverflow.com/a/34311951/1497596). – DavidRR May 26 '16 at 12:50
  • 4
    You don't always have control over callers, so a factory isn't *always* the general solution (to restate what [Damian said](http://stackoverflow.com/questions/8145479/can-constructors-be-async#comment55926301_12520574) in a more general way) – Matt Thomas Mar 22 '17 at 20:22
  • 1
    very nice solution @Pierre Poliakoff, love it – Razvan Emil Feb 06 '19 at 01:00
  • 2
    This is a nice solution from the "user" perspective, but it's quite common in i.e. web applications and you need a lot of boilerplate. It would be great if they would *syntactic sugar* this behavior in something similar like an async constructor. – Dirk Boer Nov 29 '19 at 08:22
  • PRoblem is in WinForms, when things are created in the InitializeComponent() method for designer support. In that case I dont think this is a relevant solution. – Ted Aug 19 '21 at 08:40
  • How would this work with dependency injection? i.e. if `BuildViewModelAsync` needed some injected classes to do some work before calling the private constructor. – fullStackChris Sep 08 '21 at 23:38
  • It's no less elegant than every Python class, because a static method returning an instance is basically the closest thing Python has to a constructor. I think Perl works the same way, as well as Objective-C if my memory serves. I personally don't think that style loses you anything. – JoelFan Oct 13 '21 at 04:45
  • @fullStackChris For dependency injection, you could put the injected object into the constructor of the class calling the static method and then pass it as a parameter into the static method. Granted, that does create a minor coupling. If you want to avoid that completely, you can go one step further and create a static initializer that takes a parameter of your DI container itself and pass that in at startup or similar so that anything calling this static method is completely unaware of construction requirements. – GrantA Jan 20 '22 at 19:48
  • @GrantA - and then the private method would be async? I think I tried this but was still running into uninitialized errors... need to check though – fullStackChris Jan 20 '22 at 20:11
  • @fullStackChris - No private method would need to be async. All async processing gets handled in the Build/Create method, which is public. (Sure, you can create helper private methods for that, which could be made async as needed, but there's no private method that would require async.) – GrantA Jan 20 '22 at 21:00
274

Constructor acts very similarly to a method returning the constructed type. And async method can't return just any type, it has to be either “fire and forget” void, or Task.

If the constructor of type T actually returned Task<T>, that would be very confusing, I think.

If the async constructor behaved the same way as an async void method, that kind of breaks what constructor is meant to be. After constructor returns, you should get a fully initialized object. Not an object that will be actually properly initialized at some undefined point in the future. That is, if you're lucky and the async initialization doesn't fail.

All this is just a guess. But it seems to me that having the possibility of an async constructor brings more trouble than it's worth.

If you actually want the “fire and forget” semantics of async void methods (which should be avoided, if possible), you can easily encapsulate all the code in an async void method and call that from your constructor, as you mentioned in the question.

svick
  • 236,525
  • 50
  • 385
  • 514
  • 5
    I think this hits it closest. `await` can so often replace `.ContinueWith` that it was easy for me to forget that it's not so simple. I'm not even sure what I was thinking anymore, but I think I was thinking that `await` ought to "return" a constructed `T` (which you point out isn't what an async method can return) because that's was constructors "return" but then when await continues, the contructor doesn't return anything because its a constructor, like `void`. I'm not even making sense anymore, but your answer was the most helpful. Thanks. – Marty Neal Nov 16 '11 at 03:01
  • 28
    "If the constructor of type T actually returned Task, that would be very confusing, I think." I disagree. Like async Dispose, it would be very natural. – drowa Nov 02 '14 at 03:04
  • 3
    "async void" Do not do that. The construction of the object is not complete. It can raise the exception which would not be handled and etc. – Eldar Apr 22 '21 at 13:39
  • *"it has to be either “fire and forget” `void`, or `Task`."* -- Stephen Cleary calls the `async void` methods [fire and crash](https://stackoverflow.com/questions/17659603/async-void-asp-net-and-count-of-outstanding-operations/17660475#17660475). Which is fair, because exceptions in `async void` methods are crashing the process by default. – Theodor Zoulias Jan 26 '23 at 07:13
84

Your problem is comparable to the creation of a file object and opening the file. In fact there are a lot of classes where you have to perform two steps before you can actually use the object: create + Initialize (often called something similar to Open).

The advantage of this is that the constructor can be lightweight. If desired, you can change some properties before actually initializing the object. When all properties are set, the Initialize/Open function is called to prepare the object to be used. This Initialize function can be async.

The disadvantage is that you have to trust the user of your class that he will call Initialize() before he uses any other function of your class. In fact if you want to make your class full proof (fool proof?) you have to check in every function that the Initialize() has been called.

The pattern to make this easier is to declare the constructor private and make a public static function that will construct the object and call Initialize() before returning the constructed object. This way you'll know that everyone who has access to the object has used the Initialize function.

The example shows a class that mimics your desired async constructor

public MyClass
{
    public static async Task<MyClass> CreateAsync(...)
    {
        MyClass x = new MyClass();
        await x.InitializeAsync(...)
        return x;
    }

    // make sure no one but the Create function can call the constructor:
    private MyClass(){}

    private async Task InitializeAsync(...)
    {
        // do the async things you wanted to do in your async constructor
    }

    public async Task<int> OtherFunctionAsync(int a, int b)
    {
        return await ... // return something useful
    }

Usage will be as follows:

public async Task<int> SomethingAsync()
{
    // Create and initialize a MyClass object
    MyClass myObject = await MyClass.CreateAsync(...);

    // use the created object:
    return await myObject.OtherFunctionAsync(4, 7);
}
Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116
  • 1
    ... But the return of an async method must be a Task? How do you get around that? – Malte R Nov 04 '15 at 09:31
  • 5
    the ideas is not to use a constructor, but a static function that constructs the object ans async Initializes it. So don't do the initialization in the constructor, but in a separate private Initialize function, this Initialize function can return an awaitable Task and thus the static Create function can return an awaitable Task – Harald Coppoolse Nov 04 '15 at 10:57
  • 5
    I'm referring to this as the `async constructor pattern` from now on. -- IMO, this should be the accepted answer, because it's nice, simple, and too the point -- Nice work! – BrainSlugs83 Aug 14 '18 at 20:08
  • This was very helpful, thanks for sharing! and in enough detail to make it simple to understand. kudos – Seabizkit Apr 24 '19 at 07:15
  • Tried it with code-behind of XAML View file (Xamarin.Forms) and I suppose this way of solving the problem is not applicable for my context. Thanks for the idea anyway @HaraldCoppoolse . Error makes total sense: `Type 'MyClassViewModel' is not usable as an object element because it is not public or does not define a public parameterless constructor or a type converter.` – s3c Aug 24 '21 at 10:19
  • So why not define the class public then? The only thing you should not do, is to declare the constructor public. Since you won't call this constructor, you don't need a public constructor. If you can't call `CreateAsync` from XAML, why not use code-behind? – Harald Coppoolse Aug 27 '21 at 21:11
  • Having a private constructor inhibits the use of that class through dependency injection, making the injection process more complex, isn't it? – Maxim V. Pavlov Dec 28 '21 at 10:04
  • If using it in code behind, could you move the functionality to OnAppearing? protected override async void OnAppearing() { base.OnAppearing(); await MethodToUpdateData(); } – Mal Feb 28 '23 at 11:48
5

if you make constructor asynchronous, after creating an object, you may fall into problems like null values instead of instance objects. For instance;

MyClass instance = new MyClass();
instance.Foo(); // null exception here

That's why they don't allow this i guess.

Emir Akaydın
  • 5,708
  • 1
  • 29
  • 57
  • You would think so, but that actually doesn't make sense even. If you make a call like 'var o = sqlcmd.BeginExecuteReader();' it's going to assign an IAsyncResult object to o before it continues to the next line. In your example, it can't assign anything to instance until the constructor is completed so it just doesn't make sense to allow the constructor to be asynchronous. – Brandon Moore Nov 16 '11 at 02:01
  • The way I was expecting (hoping actually, "expect" is too strong a word) it to behave was to return the constructed object, but the object would finish constructing when what it was awaiting was ready. Since I think of await as being more of a set-up-a-continuation-and-then-return, I was hoping this might be possible. I wouldn't expect null to be returned. – Marty Neal Nov 16 '11 at 02:36
  • 2
    Allowing half constructed objects (as is implicit by an async constructor) would break other language constructs, such as the guarantees made by the `readonly` keyword. – spender Nov 30 '11 at 11:22
  • 4
    If the constructor of a class C was truly Async you would get a Task that you would have to await. – Ykok Aug 17 '16 at 08:24
4

In this particular case, a viewModel is required to launch the task and notify the view upon its completion. An "async property", not an "async constructor", is in order.

I just released AsyncMVVM, which solves exactly this problem (among others). Should you use it, your ViewModel would become:

public class ViewModel : AsyncBindableBase
{
    public ObservableCollection<TData> Data
    {
        get { return Property.Get(GetDataAsync); }
    }

    private Task<ObservableCollection<TData>> GetDataAsync()
    {
        //Get the data asynchronously
    }
}

Strangely enough, Silverlight is supported. :)

Dmitry Shechtman
  • 6,548
  • 5
  • 26
  • 25
3

I was just wondering why we can't call await from within a constructor directly.

I believe the short answer is simply: Because the .Net team has not programmed this feature.

I believe with the right syntax this could be implemented and shouldn't be too confusing or error prone. I think Stephen Cleary's blog post and several other answers here have implicitly pointed out that there is no fundamental reason against it, and more than that - solved that lack with workarounds. The existence of these relatively simple workarounds is probably one of the reasons why this feature has not (yet) been implemented.

tsemer
  • 2,959
  • 3
  • 29
  • 26
1

calling async in constructor maybe cause deadlock, please refer to http://social.msdn.microsoft.com/Forums/en/winappswithcsharp/thread/0d24419e-36ad-4157-abb5-3d9e6c5dacf1

http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115163.aspx

Sylvain Rodrigue
  • 4,751
  • 5
  • 53
  • 67
Tealc Wu
  • 486
  • 1
  • 5
  • 11
  • 1
    That's about calling an `async` method *from* a constructor (which is possible, but probably not a good idea). This question is about the *constructor itself* being `async` (which won't compile at all). – Andrew Barber Nov 07 '12 at 21:58
  • Many answers are saying "there's no reason it shouldn't be possible", this is a good reason -- also, if libraries start doing async stuff in their constructors (i.e. even .Wait() or .GetResult()) it can cause other issues; for example ASP.NET web forms requires special configuration for async calls to work (i.e. it's not a deadlock, but the execution context just drops off somewhere and never comes back -- even after configuration, it only works within certain parts of the page life cycle...) -- in general, I think hiding async calls in synchronous methods should be considered an anti-pattern. – BrainSlugs83 Aug 14 '18 at 20:22
0

you can use Action inside Constructor

 public class ViewModel
    {
        public ObservableCollection<TData> Data { get; set; }
       public ViewModel()
        {              
            new Action(async () =>
            {
                  Data = await GetDataTask();
            }).Invoke();
        }

        public Task<ObservableCollection<TData>> GetDataTask()
        {
            Task<ObservableCollection<TData>> task;
            //Create a task which represents getting the data
            return task;
        }
    }
Sanjay Patel
  • 955
  • 1
  • 8
  • 22
0

Some of the answers involve creating a new public method. Without doing this, use the Lazy<T> class:

public class ViewModel
{
    private Lazy<ObservableCollection<TData>> Data;

    async public ViewModel()
    {
        Data = new Lazy<ObservableCollection<TData>>(GetDataTask);
    }

    public ObservableCollection<TData> GetDataTask()
    {
        Task<ObservableCollection<TData>> task;

        //Create a task which represents getting the data
        return task.GetAwaiter().GetResult();
    }
}

To use Data, use Data.Value.

johnsmith
  • 515
  • 5
  • 12
0

C# doesn't allow async constructors. Constructors are meant to return fast after some brief initialization. You don't expect and you don't want to wait for an instance i.e. the constructor to return. Therefore, even if async constructors were possible, a constructor is not a place for long-running operations or starting background threads. The only purpose of a constructor is initialization of instance or class members to a default value or the captured constructor parameters. You always create the instance and then call DoSomething() on this instance. Async operations are no exception. You always defer expensive initialization of members.

There are a few solutions to avoid the requirement of async constructors.

  1. A simple alternative solution using Lazy<T> or AsyncLazy<T> (requires to install the Microsoft.VisualStudio.Threading package via the NuGet Package Manager). Lazy<T> allows to defer the instantiation or allocation of expensive resources.
public class OrderService
{
  public List<object> Orders => this.OrdersInitializer.GetValue();
  private AsyncLazy<List<object>> OrdersInitializer { get; }

  public OrderService()
    => this.OrdersInitializer = new AsyncLazy<List<object>>(InitializeOrdersAsync, new JoinableTaskFactory(new JoinableTaskContext()));

  private async Task<List<object>> InitializeOrdersAsync()
  {
    await Task.Delay(TimeSpan.FromSeconds(5));
    return new List<object> { 1, 2, 3 };
  }
}

public static void Main()
{
  var orderService = new OrderService();

  // Trigger async initialization
  orderService.Orders.Add(4);
}
  1. You can expose the data using a method instead of a property
public class OrderService
{
  private List<object> Orders { get; set; }

  public async Task<List<object>> GetOrdersAsync()
  {
    if (this.Orders == null)
    {
      await Task.Delay(TimeSpan.FromSeconds(5));
      this.Orders = new List<object> { 1, 2, 3 };
    }
    return this.Orders;
  }
}

public static async Task Main()
{
  var orderService = new OrderService();

  // Trigger async initialization
  List<object> orders = await orderService.GetOrdersAsync();
}
  1. Use an InitializeAsync method that must be called before using the instance
public class OrderService
{
  private List<object> orders;
  public List<object> Orders 
  { 
    get
    {
      if (!this.IsInitialized)
      {
        throw new InvalidOperationException(); 
      }
      return this.orders;
    }
    private set
    {
      this.orders = value;
    }
  }

  public bool IsInitialized { get; private set; }

  public async Task<List<object>> InitializeAsync()
  {
    if (this.IsInitialized)
    {
      return;
    }

    await Task.Delay(TimeSpan.FromSeconds(5));
    this.Orders = new List<object> { 1, 2, 3 };
    this.IsInitialized = true;
  }
}

public static async Task Main()
{
  var orderService = new OrderService();

  // Trigger async initialization
  await orderService.InitializeAsync();
}
  1. Instantiate the instance by passing the expensive arguments to the constructor
public class OrderService
{
  public List<object> Orders { get; }

  public async Task<List<object>> OrderService(List<object> orders)
    => this.Orders = orders;
}

public static async Task Main()
{
  List<object> orders = await GetOrdersAsync();

  // Instantiate with the result of the async operation
  var orderService = new OrderService(orders);
}

private static async Task<List<object>> GetOrdersAsync()
{
  await Task.Delay(TimeSpan.FromSeconds(5));
  return new List<object> { 1, 2, 3 };
}
  1. Use a factory method and a private constructor
public class OrderService
{
  public List<object> Orders { get; set; }

  private OrderServiceBase()  
    => this.Orders = new List<object>();

  public static async Task<OrderService> CreateInstanceAsync()
  {
    var instance = new OrderService();
    await Task.Delay(TimeSpan.FromSeconds(5));
    instance.Orders = new List<object> { 1, 2, 3 };
    return instance;
  }
}

public static async Task Main()
{
  // Trigger async initialization  
  OrderService orderService = await OrderService.CreateInstanceAsync();
}
BionicCode
  • 1
  • 4
  • 28
  • 44
0

The most upvoted, yet not accepted answer, can also be modified and improved imo.

What you could do is something like this instead :

public class ViewModel       
{       
    public TData Data { get; set; }

    private ViewModel() {}
      
    public static async Task<ViewModel> BuildViewModelAsync()  
    {       
        ViewModel vm = new ViewModel();
        vm.Data = await vm.GetDataTask(); 
        return vm;
    }       

    private async Task<TData> GetDataTask(){...}
}  
matreurai
  • 147
  • 12
-1

Please bump this language request:

https://github.com/dotnet/csharplang/discussions/419

The amount of boilerplate code everyone needs to write to have a fully initialized async object is crazy and completely opposite of the trend in C# (less boilerplate).

Dirk Boer
  • 8,522
  • 13
  • 63
  • 111
-2

I would use something like this.

 public class MyViewModel
    {
            public MyDataTable Data { get; set; }
            public MyViewModel()
               {
                   loadData(() => GetData());
               }
               private async void loadData(Func<DataTable> load)
               {
                  try
                  {
                      MyDataTable = await Task.Run(load);
                  }
                  catch (Exception ex)
                  {
                       //log
                  }
               }
               private DataTable GetData()
               {
                    DataTable data;
                    // get data and return
                    return data;
               }
    }

This is as close to I can get for constructors.

tomcat
  • 1,798
  • 2
  • 11
  • 14
-2

you can create a wrapper and inject a functor representing the constructor:

class AsyncConstruct<T>
    where T: class
{
    private readonly Task<T> m_construction;
    private T m_constructed;
    public AsyncConstruct(Func<T> createFunc)
    {
        m_constructed = null;
        m_construction = Task.Run(()=>createFunc());
    }

    public T Get()
    {
        if(m_constructed == null)
        {
            m_constructed = m_construction.Result;
        }
        return m_constructed;
    }
}
-5

I use this easy trick.

public sealed partial class NamePage
{
  private readonly Task _initializingTask;

  public NamePage()
  {
    _initializingTask = Init();
  }

  private async Task Init()
  {
    /*
    Initialization that you need with await/async stuff allowed
    */
  }
}
-6

I'm not familiar with the async keyword (is this specific to Silverlight or a new feature in the beta version of Visual Studio?), but I think I can give you an idea of why you can't do this.

If I do:

var o = new MyObject();
MessageBox(o.SomeProperty.ToString());

o may not be done initializing before the next line of code runs. An instantiation of your object cannot be assigned until your constructor is completed, and making the constructor asynchronous wouldn't change that so what would be the point? However, you could call an asynchronous method from your constructor and then your constructor could complete and you would get your instantiation while the async method is still doing whatever it needs to do to setup your object.

Brandon Moore
  • 8,590
  • 15
  • 65
  • 120
  • Moreover, what would it assign to o while it's waiting on the constructor to complete? I know the natural tendency is to think it should be null, but that's not how it works. You would never get null returned without threading... using threading doesn't change that. – Brandon Moore Nov 16 '11 at 01:32
  • think about "var o;" only without "new MyObject()". that's what you get before constructor finishes its job. since making constructor async doesn't seem to be possible, we cannot test atomic times but we can assume it holds the same status with "var o;" only until it gets constructed. – Emir Akaydın Nov 16 '11 at 01:42
  • 'var o;' is not a valid statement. But let's assume we were specifying the type. In the first line you'd have 'object o;' and the second line would be 'o = new MyObject()'. Now, it HAS to assign something to o before it can go to the next line... there inlies the problem because it can't until the constructor is finished. – Brandon Moore Nov 16 '11 at 01:56
  • it would return `Task()`, obviously. – BrainSlugs83 Aug 14 '18 at 20:23