Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AddSingleton with async Invoke?

I add a singleton like this.

In Startup.cs, I add the following:

services.AddSingleton<MySingleton>();

I want to build my singleton like this (which is not possible of course):

public class MySingleton
{
    public MySingleton()
    {
        await InitAsync();
    }

    private async Task InitAsync()
    {
        await Stuff();
    }
}

How can I solve this problem without creating deadlocks?

like image 288
Erwin Wildenburg Avatar asked Mar 11 '17 00:03

Erwin Wildenburg


2 Answers

As far as I can tell, configuration in ASP.NET Core is not asynchronous, so there is no way to add a service with async factory, or anything like that.

Because of that and considering that blocking is not a big issue if it's only done once when application starts, I think you should block when creating the service. And since ASP.NET Core does not have a synchronization context, this will also not cause a deadlock.

like image 92
svick Avatar answered Sep 19 '22 11:09

svick


Use the Microsoft.VisualStudio.Threading NuGet package and then design your class like this:

public class Singleton {

  private static readonly AsyncLazy<Singleton> instance =
      new AsyncLazy<Singleton>( CreateAndDoSomething );

  private Singleton() {
  }

  // This method could also be an async lambda passed to the AsyncLazy constructor.
  private static async Task<Singleton> CreateAndDoSomething() {
     var ret = new Singleton();
     await ret.InitAsync();
     return ret;
  }

  private async Task InitAsync() {
     await Stuff();
  }

  public static AsyncLazy<Singleton> Instance
  {
     get { return instance; }
  }
}

Usage:

Singleton singleton = Singleton.Instance;

More on Asynchronous Lazy Initialization.

like image 22
CodingYoshi Avatar answered Sep 21 '22 11:09

CodingYoshi