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.
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;
}
}
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.
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);
}
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.
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. :)
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.
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
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.
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.
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);
}
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();
}
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();
}
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 };
}
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();
}
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;
}
}
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;
}
}
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).
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.
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
*/
}
}
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.
Related
I have a parent-child class structure where parent class in constructor creates instance of the child class and use one of child class async methods with .Result approach.
public class ParentClass
{
private readonly ChildClass _childClass;
public ParentClass()
{
_childClass = new ChildClass();
bool result = _childClass.GetSomething().Result;
}
}
public class ChildClass
{
public ChildClass()
{
}
public async Task<bool> GetSomething()
{
return await Task.FromResult<bool>(false);
}
}
My goal is to remove .Result and change it with normal await keyword. I can create static async method, there create instance of the child class, later call constructor and pass instance.
public class ParentClass2
{
private readonly ChildClass _childClass;
private ParentClass2(ChildClass childClass, bool result)
{
_childClass = childClass;
}
public static async Task<ParentClass2> GetInstance()
{
ChildClass childClass = new ChildClass();
bool result = await childClass.GetSomething();
return new ParentClass2(childClass, result);
}
}
But then I have 2 problems:
The more parents of parents [..of parents] I have - the more code I have to modify in a same way.
Highest level classes use DI. And with async I can't do this
services.AddScoped<ParentClass2>(async p =>
{
var instance = await ParentClass2.GetInstance();
return instance;
});
Any suggestions?
When you deal with dependency injection and asynchronous initialization, you have to make compromises.
In general, I approach this one of two ways.
If the asynchronous initialization is done once at startup, you can extract the asynchronous call out before the DI is set up, run it synchronously, and inject the results into the constructors for your types at DI setup.
The other option is to essentially do the asynchronous initialization on-demand whenever any other method is called. The constructor could start it, and every method would (asynchronously) wait for the initialization to complete. This does have the side effect that the entire API has to be asynchronous. Either that, or you change the DI type to be an asynchronous factory which then asynchronously creates the type with your actual API.
This question already has answers here:
Can constructors be async?
(15 answers)
Async method which is called from constructor [duplicate]
(2 answers)
c# start async method within object constructor - bad practice? [closed]
(6 answers)
Closed 2 years ago.
I've been trying to find a design for the situation where you have a type that has a dependency and you want to call a method that returns a Task. The gut reaction is to do GetAwaiter().GetResult() but I know that goes against the whole purpose of asynchronous tasks. The thought is to spin up the task but let it do its thing until the type needs it.
public class SomeClass {
private readonly Task<Data> _getDataTask;
private readonly IDependency _dep;
private Data _data;
public SomeClass(IDependency dep) {
_dep = dep;
// I'll spin this up but I don't need the result yet
_getDataTask = _dep.GetDataAsync();
}
public async Task DoSomeWork() {
// Now I need the result of the task so I'll await the task
_data = await _getDataTask;
ExecuteWorkOn(_data);
}
}
Maybe this approach would produce a lot of condition statements to await if you don't have the result cached? I'm hoping to get feedback on this approach in the hopes that either another SO question gets linked or we come up with a design we didn't think about before.
UPDATE 1
I made the Task to be Task<Data> as mentioned in one of the comments
There are two good solutions for this problem:
First:
Use a async init methode in the constructor and hold the resulting Task in a property. This way the calling code can await the completion if the initilisation.
public class Foo
{
public Task InitTask { get; private set; }
public Foo()
{
this.InitTask = this.Init();
}
private async Task Init() { ... }
}
can be used like this
var newFoo = new Foo();
await newFoo.InitTask();
// can now use newFoo
Second:
Use a use only private constructors and have a Create methode which you use to create intances for your class
public class Foo
{
public Foo() { }
public async Task<Foo> Create()
{
var newFoo = new Foo();
await newFoo.Init();
return newFoo;
}
private async Task Init() { ... }
}
can be used like this
var newFoo = await Foo.Create();
Your approch, if not bad, is a variant of approch 1 but would mean that you need to await the task started in the constructor in every methode that needs the result (or side effect) of the task.
public class Foo
{
private Task InitTask { get; private set; }
public Foo()
{
this.InitTask = this.Init();
}
private async Task Init() { ... }
public async Task DoStuffA()
{
await this.InitTask;
// do work
}
public async Task DoStuffB()
{
await this.InitTask;
// do work
}
public async Task DoStuffC()
{
await this.InitTask;
// do work that could be done without async/await
}
}
So I would recommend approch 2 to do async initialization.
I am trying to run non static method from static and use dependency Injection inside non static method. (I am trying to do this inside one class)
My code looks like this:
public class Tokens
{
private IRefreshTokenRepository refreshTokenRepository;
public Tokens(IRefreshTokenRepository refreshTokenRepository)
{
this.refreshTokenRepository = refreshTokenRepository;
}
// I understand that problem is there, but I should to write this
//constructor because otherwise I can not use class variable in static method
public Tokens()
{
}
public static async Task<string> GenerateJwt()
{
RefreshToken rf = new RefreshToken{...};
Tokens t = new Tokens();
t.StoreRefToken(rf);
return JsonConvert.SerializeObject(...);
}
public async void StoreRefToken(RefreshToken reft)
{
this.refreshTokenRepository.InsertRefreshToken(reft);
await refreshTokenRepository.SaveAsync();
}
}
As you understand from code, when I wrote "Tokens t = new Tokens();" this code had used constructor without importing repository. What to do? Can I fix it inside single class?
Thank you
P.S. if question is silly I'm sorry
Static and Dependency Injection do not play well together.
Keep Tokens as an instance class and abstract it
public interface ITokenService {
Task<string> GenerateJwt();
}
so that it can be injected as a dependency.
derive Tokens from the abstraction
public class Tokens: ITokensService {
private readonly IRefreshTokenRepository refreshTokenRepository;
public Tokens(IRefreshTokenRepository refreshTokenRepository) {
this.refreshTokenRepository = refreshTokenRepository;
}
public async Task<string> GenerateJwt() {
RefreshToken rf = new RefreshToken{...};
await StoreRefToken(rf);
return JsonConvert.SerializeObject(...);
}
private async Task StoreRefToken(RefreshToken reft) {
this.refreshTokenRepository.InsertRefreshToken(reft);
await refreshTokenRepository.SaveAsync();
}
}
Now you have access to the desired members where ever it is needed as a dependency
I'm referencing a class that performs various demanding operations using callbacks rather than async operations. For example:
class CallbackClass : SomeSdkCallbacks
{
public void RequestData()
{
// We call this to request some data.
// After some time, this will trigger OnDataReturned to be called
}
public void OnDataReturned(DataObject data)
{
// This will be called automatically with returned data via SomeSdkCallbacks
}
}
There are many instances of this type of structure throughout this class.
What I'm trying to do is create a wrapper class around this one that simplifies it's usage. The structure that I'm going for at the moment is:
class MyWrapperClass
{
CallbackClass CallbackClass;
public MyWrapperClass()
{
this.CallbackClass = new CallbackClass();
}
public DataObject GetData()
{
this.CallbackClass.RequestData();
// Somehow wait until this.CallbackClass.OnDataReturned is called?
// Somehow get the data that would be passed in to this.CallbackClass.OnDataReturned()???
}
}
What is the best method of wrapping up a 'callback' architecture into a single asynchronous method?
Edit: To clarify, ideally I would like to package this up into a single method that can return the data in a single request. See the MyWrapperClass.GetData() method in my example for my ideal structure.
Edit 2: I'm aware that this desired architecture is bad form. Unfortunately that is the requested structure that has been asked of me.
I think this is what you want:
class CallbackClass<T>
{
private TaskCompletionSource<T> task = new TaskCompletionSource<T>();
public void RequestData()
{
}
public void OnDataReturned(T data)
{
task.SetResult(data);
}
public Task<T> Task { get { return task.Task; } }
}
class MyWrapperClass
{
public Task<DataObject> GetData()
{
var cls = new CallbackClass<DataObject>();
cls.RequestData();
return cls.Task;
}
}
Just note that TaskCompletionSource must be created per operation so you don't use the same one for two different calls. With this you can use the async keyword. This might help a bit more.
In your situation you can add some event on CallBackClass.
Like here:
class CallbackClass : SomeSdkCallbacks
{
public event Action<object> DataReturnedEvent;
public void RequestData()
{
// We call this to request some data.
// After some time, this will trigger OnDataReturned to be called
}
public void OnDataReturned(DataObject data)
{
DataReturnedEvent?.Invoke(data);
}
}
And you can use the event in the wrapper class
class MyWrapperClass
{
CallbackClass CallbackClass;
public MyWrapperClass()
{
this.CallbackClass = new CallbackClass();
CallbackClass.DataReturnedEvent =+ ProcessData;
}
private void ProcessData(object Data)
{
//some data processing
}
public DataObject GetData()
{
this.CallbackClass.RequestData()
}
}
Consider the following code:
public interface IBar
{
Task<IEnumerable<string>> GetStringsAsync();
}
public class Foo
{
public Foo(IBar bar, IList<string> initial)
{
MyCollection = new ObservableCollection<string>();
if (initial == null || !initial.Any())
AddContent(bar);
else
MyCollection.AddRange(initial);
}
public ObservableCollection<string> MyCollection { get; private set; }
public void AddContent(IBar bar)
{
var cancel = new CancellationTokenSource();
bar.GetStringsAsync().ContinueWith(
task => MyCollection.AddRange(task.Result),
cancel,
TaskContinuationOptions.NotOnCancel,
TaskScheduler.FromCurrentSynchronizationContext());
}
}
How can I unit test the Foo.AddContent method? I'd like to test that the strings my mock IBar provides do, in fact, get added to the collection, but the asserts always get called before the task has updated the collection.
I'm using .NET 4.5.2. My first choice would have been to use async and await in AddContent, but because the method is used in the constructor I thought it would be best to avoid that. I need something that can initiate the asynchronous loading of data but that will not wait for it to finish.
Recommendations on how to rewrite AddContent are welcome, but I've already tried a lot of things and this is the only one that has worked well, so what I'd really like is a way to test it.
Update 2
Use Stephen Cleary's Asynchronous Initialization pattern found here.
http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html
Update
Since the question has changed, the requirement is now to have the constructor take on the variable IBar. I would suggest the following based on the hard requirement of the IBar variable being passed into the constructor:
public class Foo
{
public Foo(IBar bar)
{
MyCollection = new ObservableCollection<string>();
MyCollection.AddRange(bar.GetStringsAsync().Result));
}
public ObservableCollection<string> MyCollection { get; private set; }
public async Task AddContent(IBar bar)
{
MyCollection.AddRange(await bar.GetStringsAsync());
}
}
NOTE: the public method still utilizes the preferred mechanism async / await, but the constructor simply calls .Result. This is a blocking call in the constructor and a very poor practice. This could easily be argued to be something that you should never, ever do...
I highly suggest that your constructor takes the initial strings instead as such, (especially considering that it is only being used for the strings that it returns!):
public class Foo
{
public Foo(IEnumerable<string> strings)
{
MyCollection = new ObservableCollection<string>();
MyCollection.AddRange(strings);
}
public ObservableCollection<string> MyCollection { get; private set; }
public async Task AddContent(IBar bar)
{
MyCollection.AddRange(await bar.GetStringsAsync());
}
}
Usage
[TestMethod]
public async Task Test()
{
IBar bar = GetMockedBarImpl();
var sut = new Foo(await bar.GetStringsAsync());
Assert.IsTrue(sut.MyCollection.Any());
// TODO: Add asserts for known strings in collection...
}
looks like there is an inherit race condition with the code in question. I would wait for GetStringAsync to complete and assign to MyCollection.
public void AddContent(IBar bar)
{
var cancel = new CancellationTokenSource();
var result = bar.GetStringsAsync().ContinueWith(
task => task.Result,
cancel,
TaskContinuationOptions.NotOnCancel,
TaskScheduler.FromCurrentSynchronizationContext());
MyCollection.AddRange(result.Result);
}
or simply
public void AddContent(IBar bar)
{
var result = bar.GetStringsAsync().Result;
MyCollection.AddRange(result);
}