Await an async function from setter property - c#

I need to await to an async function from a property setter method.
public String testFunc()
{
get
{
}
set
{
//Await Call to the async func <asyncFunc()>
}
}
I understand we should not make async properties, so what is the optimal way to do this.

You can't make async properties and you shouldn't want to - properties imply fast, non blocking operations. If you need to perform a long running activity, as implied by you're wanting to kick of an async operation and wait for it, don't make it a property at all.
Remove the setter and make a method instead.

Use
public bool SomeMethod
{
get { /* some code */ }
set
{
AsyncMethod().Wait();
}
}
public async Task AsyncMethod() {}
[EDIT]

You can't use async function with property
Alternative Can use Result Property
public string UserInfo
{
get => GetItemAsync().Result;
}

Related

awaiting inside an awaitable function in .net

I have a function that returns a Task
class Sample
{
TaskCompletionSource<int> _tcs;
..
public Task<int> DoIt(){
StartDoingStuff();
return _tcs.Task;
}
..
private void FinshedStuffCallBack(){
_tsc.SetResult(42);
}
}
Caller goes
var sample = new Sample();
var result = await Sample.DoIt();
works fine
Now I need to do something in addition in DoIt, this is itself awaitable
I naively tried
public async Task<int> DoIt(){
await DoOtherAsyncStuff();
StartDoingStuff();
return _tcs.Task;
}
but this is not allowed
CS4016 Since this is an async method, the return expression must be of
type 'int' rather than 'Task'
OK I get what its trying to say, but thats not my intention, I dont have the return value yet, it comes once StartDoingStuff triggers the callback.
Not sure what to try next.
Most likely you just need (note the await on the last line):
public async Task<int> DoIt()
{
await DoOtherAsyncStuff();
StartDoingStuff();
return await _tcs.Task;
}
await is needed on the last line because an async function returning Task<int> needs to return int, while _tcs.Task is a Task<int>. Using await will wait for the Task's completion and return the int which is what we need.
However, depending on your complete code you may want something else. For example if you're doing more complicated things with TaskCompletionSource you may need to remove async for this definition and do something like
public Task<int> DoIt()
{
return DoOtherAsyncStuff().ContinueWith(_ =>
{
StartDoingStuff();
return _tcs.Task;
}, TaskCompletionOptions.ExecuteSynchronously);
}
In general it's best not to mess with TaskCompletionSource unless you're doing something more advanced, for example providing an async abstraction of something synchronous/callback based. Hence a complete code example may change my answer (for example what's the body of StartDoingStuff + DoOtherAsyncStuff?).

stop bubbling up Async await Task to caller without getting deadlock

I have a problem where I have a library that uses an async function, GetParametersByPathAsync (which is defined here: https://github.com/aws/aws-sdk-net/blob/master/sdk/src/Services/SimpleSystemsManagement/Generated/_mobile/AmazonSimpleSystemsManagementClient.cs#L2718)
I have a library function defined as
Task<Dictionary<string,string>> GetAllParameters(string region)
{
var pars = DoParameterGatheringWork(reigion);
...(do some more work)
return dict;
}
which calls another method
async Task<Dictionary<string,string>> DoParameterGatheringWork(string region)
{
...
var response = await GetParametersByPathAsync(requestObj);
... (process the response)
return parameterDict;
}
that awaits on the GetParametersByPathAsync and gathers things.
This is a problem because GetAllParameters has to be called by my service from a static constructor and initialize a parameter Dictionary<string,string> MyParameters { get; }
I would like to stop this bubbling up of Tasks at some point in the library, so it can just expose Dictionary<string,string> GetAllParameters(string region), not the Task version. (I am completely fine with it becoming synchronous..)
I don't think I should be just doing Task.Wait() or Task.Result either because that will cause deadlocks.
Maybe this isn't the best way to go about it, but I am unsure how to continue on from here.
Any thoughts would be appreciated!
Edit:
Here is the constructor code I would like to have:
public class MyConfiguration
{
static MyConfiguration()
{
...
Parameters = ServiceConfiguration.GetAllParameters(); // (library call)
}
public static Dictionary<string, string> Parameters { get; }
}
and the client will be able to use this anywhere just by MyConfiguration.Parameters["IAMAPARAMETER"]
After comment: at the end of this answer: How to call the async method from a non-async method
Apparently DoParameterGatheringWork is a function that normally would have to do some busy waiting for another process, like a database, or a file, or some information from the internet.
The designer of that function thought it would be a waste of time if your thread would be waiting idly for the result of this remove action. Therefore he decided to make it async, so the callers could do other things while the other process would process the request.
You saw correct that this means that all callers should also be async, and that a constructor can't be async.
If you want to benefit from the advantages of async-await (meaning that your callers can continue processing instead of idly waiting, make your constructor ligthweight and let some Create function do the async job you normally would do in the constructor. Force everyone who wants an object of your class to use this async Create function.
public class MyConfiguration
{
// Static async Create function, does everything you'd normally do in the constructor:
public static async Task<MyConfiguration> CreateAsync()
{
Dictionary<string,string> allParameters = await ServiceConfiguration.GetAllParameters(...);
MyConfiguration createdConfiguration = new MyConfiguration(allParameters);
return createdConfiguration;
}
// make sure that no one except CreateAsync can call the constructor:
private MyConfiguration(Dictionary<string,string> allParameters)
{
parameters = allParameters;
}
}
What you do is that you make the constructor as lightweight as possible and do all the difficult stuff, including await in the CreateAsync function.
Usage:
The following will lead to compiler error, so you know the problem before you start running:
MyConfiguration config = new MyConfiguration(...);
Proper usage:
async Task<...> DoSomethingAsync(...)
{
...
// I need a configuration:
MyConfiguration config = await MyConfiguration.Create();
// from here you can use the fully initialized MyConfiguration object:
config.DoSomethingElse();
...
}
Simple comme bonjour
Addition: how to call async method from a non-async function
To call an async function from a non-async method, use Task.Run to start the async function, Task.Wait to wait for the async function to complete and Task.Result to get the return value of the async function.
static void Main(string[] args)
{
// call an async function:
var asyncTask = Task.Run( () => MyAsyncFunction(...));
// if desired: do other things
DoSomethingElse();
// now you need the result of the async function
asyncTask.Wait();
var returnValue = asyncTask.Result;
Process(returnvalue);
}

Call async method from property setter

I have a couple of places where I do this, but it's not feasible/practical to rework the code. However it seems that the method can just be called "normally", e.g.:-
set
{
...
DoSomethingAsync();
}
A squiggle appears in the VS editor under this line, with this tooltip warning:-
Because this call is not awaited, execution of the current method continues before the call is completed.
Without the async/await keywords I kind of expected that the method would end up being called synchronously. What am I not getting here?
If I change the line to the following then the squiggle/warning disappears:-
DoSomethingAsync().Wait();
Presumably this turns it into a blocking call?
And purely out of curiosity, what would be the implications of doing the following:-
Task.Run(() => DoSomethingAsync());
Without the async/await keywords I kind of expected that the method would end up being called synchronously. What am I not getting here?
Your assumption is wrong: an async method is always called asynchronously. Unless you Wait() it, it will not wait until the async method is done. Wait() will indeed block the call to your async method. Even if you do Task.Run, it will run asynchonously (twice, since it async method runs asynchronously within your Task.Run).
Properties can't be called asynchronously, so a Get method would do the trick here. That way you can make your code asynchronous all the way.
Call Async method within a property setter (MVVM usage)
Create the method
public class AsyncRunner
{
public static void Run(Task task, Action<Task> onError = null)
{
if (onError == null)
{
task.ContinueWith((task1, o) => { }, TaskContinuationOptions.OnlyOnFaulted);
}
else
{
task.ContinueWith(onError, TaskContinuationOptions.OnlyOnFaulted);
}
}
}
Call it within a setter property
private NavigationMenuItem _selectedMenuItem;
public NavigationMenuItem SelectedMenuItem
{
get { return _selectedMenuItem; }
set
{
_selectedMenuItem = val;
AsyncRunner.Run(YourAsyncMethod(_selectedMenuItem));
}
}
This is the async method that needs to be run...
private async Task YourAsyncMethod(NavigationMenuItem newNavigationMenu)
{
//call async tasks...
}
If you look at the definition of DoSomethingAsync() it will be something like this
public async Task<T> DoSomethingAsync()
public Task<T> DoSomethingAsync()
Either way, it will return a Task which has (probably) only just started.
You can either call .Wait() on the task, or not.
If not, you are leaving that Task to run in the background.
That's probably not the programmer's intention - hence the warning.

async Indexer in C#

Recently, we have movied to EF 6 and we have begun to use EF async commands.
For example in my repository I have the following method:
// Gets entities asynchron in a range starting from skip.
// Take defines the maximum number of entities to be returned.
public async Task<IEnumerable<TEntity>> GetRangeAsync(int skip, int take)
{
var entities = this.AddIncludes(this.DbContext.Set<TEntity>())
.OrderBy(this.SortSpec.PropertyName)
.Skip(skip)
.Take(take)
.ToListAsync();
return await entities;
}
Now I have to modfiy the UI for the async data retrieving.
Below is my UI class; This class is bound to WPF.
public sealed class RepositoryCollectionView<TEntity, TEntityViewModel> : IList<TEntityViewModel>,
ICollectionView,
IEditableCollectionView,
IComparer
...
public TEntityViewModel this[int index]
{
get
{
return await this.GetItem(index).Result;
}
set
{
throw new NotSupportedException();
}
}
...
...
...
The problem: In the UI I have create a new method which called GetItemAsync(index) and I need to call this method from the Indexer;
When I write the keyword async to the indexer like that:
public async TEntityViewModel this[int index] I get the following error "The modfier 'async' is not valid for this item"
Any idea? any help would be greatly appreciated!
You simply can't make indexers async. From section 10.15 of the C# 5 specification:
A method or anonymous function with the async modifier is called an async function.
async is listed as one of the valid modifiers for methods (section 10.6), but not for indexers (10.9).
Bear in mind that an async method can only return void, Task and Task<T> - but you wouldn't want a setter to accept a Task<T> or Task, so what would the property type usefully be? (And why even have a setter if you're not supporting it?)
Given that it sound like a caller can already use GetItem - which should be GetItemAsync if it's returning a Task<TEntityViewModel> - I don't see that an indexer is going to help you.
You technically can't make indexers async. You can however have a get indexer return a Task or return the Task from an async method. Which accomplishes the same.
public class AsyncIndexer
{
public Task<int> this[int i] => GetValue(i);
public Task<string> this[string s] => Task.Run(async () =>
{
await Task.Delay(3000);
return s;
});
private async Task<int> GetValue(int i)
{
await Task.Delay(3000);
return i;
}
}
class Program
{
static void Main(string[] args)
{
Task.Run(async () =>
{
var asyncIndexer = new AsyncIndexer();
Console.WriteLine(await asyncIndexer[2]);
}).Wait();
}
}
Unfortunately setters can't return anything, so async setters are in no way possible because the await statement needs a task to be returned.
Could you imagine the syntax?
await (asyncIndexer[2] = 2)
I'd love that :p
This isn't possible properties cannot be async. Source
What you can do is call an asyncrounous method and wait for it to complete, but it will block (no async means no await).

How to initialize an object using async-await pattern

I'm trying to follow RAII pattern in my service classes, meaning that when an object is constructed, it is fully initialized. However, I'm facing difficulties with asynchronous APIs. The structure of class in question looks like following
class ServiceProvider : IServiceProvider // Is only used through this interface
{
public int ImportantValue { get; set; }
public event EventHandler ImportantValueUpdated;
public ServiceProvider(IDependency1 dep1, IDependency2 dep2)
{
// IDependency1 provide an input value to calculate ImportantValue
// IDependency2 provide an async algorithm to calculate ImportantValue
}
}
I'm also targeting to get rid of side-effects in ImportantValue getter, to make it thread-safe.
Now users of ServiceProvider will create an instance of it, subscribe to an event of ImportantValue change, and get the initial ImportantValue. And here comes the problem, with the initial value. Since the ImportantValue is calculated asynchronously, the class cannot be fully initialized in constructor. It may be okay to have this value as null initially, but then I need to have some place where it will be calculated first time. A natural place for that could be the ImportantValue's getter, but I'm targeting to make it thread-safe and with no side-effects.
So I'm basically stuck with these contradictions. Could you please help me and offer some alternative? Having value initialized in constructor while nice is not really necessary, but no side-effects and thread-safety of property is mandatory.
Thanks in advance.
EDIT: One more thing to add. I'm using Ninject for instantiation, and as far as I understand, it doesn't support async methods to create a binding. While approach with initiating some Task-based operation in constructor will work, I cannot await its result.
I.e. two next approaches (offered as answers so far) will not compile, since Task is returned, not my object:
Kernel.Bind<IServiceProvider>().ToMethod(async ctx => await ServiceProvider.CreateAsync())
or
Kernel.Bind<IServiceProvider>().ToMethod(async ctx =>
{
var sp = new ServiceProvider();
await sp.InitializeAsync();
})
Simple binding will work, but I'm not awaiting the result of asynchronous initialization started in constructor, as proposed by Stephen Cleary:
Kernel.Bind<IServiceProvider>().To<ServiceProvider>();
... and that's not looking good for me.
I have a blog post that describes several approaches to async construction.
I recommend the asynchronous factory method as described by Reed, but sometimes that's not possible (e.g., dependency injection). In these cases, you can use an asynchronous initialization pattern like this:
public sealed class MyType
{
public MyType()
{
Initialization = InitializeAsync();
}
public Task Initialization { get; private set; }
private async Task InitializeAsync()
{
// Asynchronously initialize this instance.
await Task.Delay(100);
}
}
You can then construct the type normally, but keep in mind that construction only starts the asynchronous initialization. When you need the type to be initialized, your code can do:
await myTypeInstance.Initialization;
Note that if Initialization is already complete, execution (synchronously) continues past the await.
If you do want an actual asynchronous property, I have a blog post for that, too. Your situation sounds like it may benefit from AsyncLazy<T>:
public sealed class MyClass
{
public MyClass()
{
MyProperty = new AsyncLazy<int>(async () =>
{
await Task.Delay(100);
return 13;
});
}
public AsyncLazy<int> MyProperty { get; private set; }
}
One potential option would be to move this to a factory method instead of using a constructor.
Your factory method could then return a Task<ServiceProvider>, which would allow you to perform the initialization asynchronously, but not return the constructed ServiceProvider until ImportantValue has been (asynchronously) computed.
This would allow your users to write code like:
var sp = await ServiceProvider.CreateAsync();
int iv = sp.ImportantValue; // Will be initialized at this point
This is a slight modification to #StephenCleary pattern of async initialization.
The difference being the caller doesn't need to 'remember' to await the InitializationTask, or even know anything about the initializationTask (in fact it is now changed to private).
The way it works is that in every method that uses the initialized data there is an initial call to await _initializationTask. This returns instantly the second time around - because the _initializationTask object itself will have a boolean set (IsCompleted which the 'await' mechanism checks) - so don't worry about it initializing multiple times.
The only catch I'm aware of is you mustn't forget to call it in every method that uses the data.
public sealed class MyType
{
public MyType()
{
_initializationTask = InitializeAsync();
}
private Task _initializationTask;
private async Task InitializeAsync()
{
// Asynchronously initialize this instance.
_customers = await LoadCustomersAsync();
}
public async Task<Customer> LookupCustomer(string name)
{
// Waits to ensure the class has been initialized properly
// The task will only ever run once, triggered initially by the constructor
// If the task failed this will raise an exception
// Note: there are no () since this is not a method call
await _initializationTask;
return _customers[name];
}
// one way of clearing the cache
public void ClearCache()
{
InitializeAsync();
}
// another approach to clearing the cache, will wait until complete
// I don't really see a benefit to this method since any call using the
// data (like LookupCustomer) will await the initialization anyway
public async Task ClearCache2()
{
await InitializeAsync();
}
}
You could use my AsyncContainer IoC container which supports the exact same scenario as you.
It also supports other handy scenarios such as async initializers, run-time conditional factories, depend on async and sync factory functions
//The email service factory is an async method
public static async Task<EmailService> EmailServiceFactory()
{
await Task.Delay(1000);
return new EmailService();
}
class Service
{
//Constructor dependencies will be solved asynchronously:
public Service(IEmailService email)
{
}
}
var container = new Container();
//Register an async factory:
container.Register<IEmailService>(EmailServiceFactory);
//Asynchronous GetInstance:
var service = await container.GetInstanceAsync<Service>();
//Safe synchronous, will fail if the solving path is not fully synchronous:
var service = container.GetInstance<Service>();
I know this is an old question, but it's the first which appears on Google and, quite frankly, the accepted answer is a poor answer. You should never force a delay just so you can use the await operator.
A better approach to an initialization method:
private async Task<bool> InitializeAsync()
{
try{
// Initialize this instance.
}
catch{
// Handle issues
return await Task.FromResult(false);
}
return await Task.FromResult(true);
}
This will use the async framework to initialize your object, but then it will return a boolean value.
Why is this a better approach? First off, you're not forcing a delay in your code which IMHO totally defeats the purpose of using the async framework. Second, it's a good rule of thumb to return something from an async method. This way, you know if your async method actually worked/did what it was supposed to. Returning just Task is the equivalent of returning void on a non-async method.
I have a variation of Stephen Cleary's example of an asynchronous initialization pattern. You could encapsulate the Initialization property and await it in the class methods. In this case, the client code will not need to await the initialization task.
public class ClassWithAsyncInit
{
public ClassWithAsyncInit()
{
Initialization = InitializeAsync();
}
private Task Initialization { get; private set; }
private async Task InitializeAsync()
{
// your async init code
}
public async Task FirstMethod()
{
await Initialization;
// ... other code
}
}
The drawback is that it's not convenient if you have a lot of methods in your class and need to await the Initialization task in each one. But sometimes it is okay. Let's say you have a simple interface for saving some JSON objects:
public IDataSaver
{
void Save(string json);
}
And you need to implement it for a database with the asynchronous initialization logic. Considering that you would have only one public method it makes sense to encapsulate the Initialization property and await it in the Save method:
public class SomeDbDataSaver: IDataSaver
{
protected DatabaseClient DbClient { get; set; }
public SomeDbDataSaver()
{
DbClient = new DatabaseClient();
Initialization = InitializeAsync(); // start off the async init
}
private Task Initialization { get; private set; }
private async Task InitializeAsync()
{
await DbClient.CreateDatabaseIfNotExistsAsync("DatabaseName");
}
public async Task Save(string json)
{
await Initialization;
// ... code for saving a data item to the database
}
}

Categories

Resources