How to create an awaitable class? [duplicate] - c#

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can constructors be async
I have a class Example that pulls several information from the internet on creation.
public class Example
{
string information;
public Example()
{
//Pull information
}
}
Now I would like to let Example become awaitable because it is important that Example is created before continuing the part after creation.
public async void SetupSomething()
{
Example ex = new Example();
await ex;
// Do something with ex
}
How can I do this?

You could do that, but I think that's not a good approach, because there is nothing forcing the await before you start using the instance.
I think a good idea would be to create static asynchronous method that creates your object. Something like:
class Example
{
private Example()
{
}
private async Task InitializeAsync()
{
// get the required data asynchronously here
}
public static async Task<Example> CreateAsync()
{
var result = new Example();
await result.InitializeAsync();
return resul;
}
}

Well, the constructor should wait until it is done doing it's stuff. After all, the thread use to create it is from the method that calls it.
However, what I think would be very important, is to show us what that constructor is doing. There's a good chance it is calling something somewhere that start another thread and doesn't wait for it to resolve, making the constructor returns while not having all the "information" you are talking about.
Might be similar to: C# : Blocking a function call until condition met

Related

Is there any way to know if a method is running being awaited from within the method?

I'm a university student but, since I like programming, I try to create a library of code that's been useful to me (something like a code base).
In the process of doing this, I started designing/writing an asynchronous method that's about to be used for interlocking a variable. My goal is to produce different result when this method is being awaited (runs synchronously) and when it isn't.
An example could be the following:
private int _lock;
public async Task<bool> Lock()
{
if (method_is_not_being_awaited)
return Interlocked.Exchange(ref _lock, 1) == 0;
while (0 != Interlocked.Exchange(ref _lock, 1)) {}
return true;
}
Is there any way to achieve such result? If yes, how?
ps: I know that I could make 2 different methods bool lock() and async Task<bool> lockAsync() but, that's not what I ask for
No, it is not possible to do what you want because method must return value before any operation on result (including await) can be performed. It is not specific to async methods but rather how all code behaves in C# (and pretty much any other language).
On other hand it is pretty easy to do something that very close to what you ask - synchronously return value as soon as one tries to await the result of the method: await is essentially just call to GetAwaiter on the result and you can wire it up to alter state of your method.
Note that you can't really know what to do if method ever awaited anyway - so while you can act at moment when await is called you really can't know in advance if you should start asynchronous processing. So the best you can achieve is to do nothing in synchronous part, start asynchronous processing anyway and instantly return result when await is called (aborting/ignoring asynchronous part of the method).
Details on implementing class that can be used as result can be found in https://www.codeproject.com/Articles/5274659/How-to-Use-the-Csharp-Await-Keyword-On-Anything and https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/task-asynchronous-programming-model.
Skeleton code below shows how to implement method that does nothing unless await is called:
class MyTask
{
public MyAwaitable GetAwaiter()
{
return new MyAwaitable();
}
}
class MyAwaitable : INotifyCompletion
{
public bool IsCompleted
{
get { return true; }
}
public int GetResult()
{
return 42; // this is our "result" from method.
}
public void OnCompleted (Action continuation)
{
// just run instantly - no need to save callback as this one is
// always "completed"
continuation();
}
}
MyTask F()
{
// if your really want you can start async operation here
// and somehow wire up MyAwaitable.IsComplete to terminate/abandon
// asynchronous part.
return new MyTask();
}

Kick off async method in constructor in c#

I'm wondering is it safe to call async method in a constructor in the following way:
Let's say we have an async method Refresh that is fetching data from the internet. We are also using Reactive Extensions to notify everyone that is interested that new data was fetched.
I'm wondering is it safe to call Refresh first time in a class constructor? Can I use such construction?
Task.Run(Refresh);
or
Refresh().ConfigureAwait(false)
I'm not really interested here if the method has finished or not, since I will get notified through Reactive Extensions when data is fetched.
Is it ok to do something like this?
public class MyClass
{
BehvaiorSubject<Data> _dataObservable = new BehvaiorSubject(Data.Default);
IObservable DataObservable => _dataObservable;
public MyClass()
{
Refresh().ConfigureAwait(false);
}
public async Task Refresh()
{
try
{
var data = await FetchDataFromNetwork();
_dataObservable.OnNext(data);
}
catch (VariousExceptions e)
{
//do some appropriate stuff
}
catch(Exception)
{
//do some appropriate stuff
}
}
}
Though people are against the idea, we have similar things in our project :)
The thing is you have to properly handle any exceptions thrown from that Task in case they go unobserved. Also you might need to expose the task via either a method or a property, just so that it is possible to await (when necessary) the async part is finished.
class MyClass
{
public MyClass()
{
InitTask = Task.Delay(3000);
// Handle task exception.
InitTask.ContinueWith(task => task.Exception, TaskContinuationOptions.OnlyOnFaulted);
}
public Task InitTask { get; }
}

How do you handle a 3rd party interface returning Task if you don't have any async code? [duplicate]

This question already has answers here:
How to implement interface method that returns Task<T>?
(4 answers)
Closed 6 years ago.
I am working with a third-party dll which exposes methods which return Task and Task<T>. I don't have any control over this assembly or the interface, and I assume the author assumed everything would need to be async since the naming of the methods are *Async() as shown below.
Given that, how do I properly implement the interface if I don't actually have any asynchronous code running?
public interface IFoo
{
Task DoWorkAsync();
Task<int> GetValueAsync();
}
My attempt was the following:
public class FooBar : IFoo
{
public async Task DoWorkAsync()
{
// Do Some Work
await Task.Yield();
}
public async Task<int> GetValueAsync()
{
// Do Some Work
var result = ...;
return Task.FromResult(result);
}
}
Additionally:
Was the author correct in exposing only methods that returned Task/Task<T>?
Was the author correct in suffixing method names with *Async()? Code analysis doesn't complain if I write an async method without appending Async to the name.
If you don't have async work to do don't include the async keyword. Your GetValueAsnyc function was almost correct, you just needed to drop the async. For your DoWorkAsync you should just not mark the method async and return a completed task.
public class FooBar : IFoo
{
public Task DoWorkAsync()
{
// Do Some Work
//If you can use .NET 4.6
return Task.CompletedTask;
//For older versions, the thing you pass in does not matter, I like to use bool.
return Task.FromResult(false);
}
public Task<int> GetValueAsync()
{
// Do Some Work
var result = ...;
return Task.FromResult(result);
}
}
However, if your code is slow and you end up blocking the UI for a long period of time I would consider looking in to if you can re-write your code as actually being async or perhaps wrapping the code in to a background thread, but I would only do a background thread if it was a last resort.

Async method which is called from constructor [duplicate]

This question already has answers here:
Can constructors be async?
(15 answers)
Closed 1 year ago.
I have a question regardin the async method which I call in constructor and how to solve or is there a good work around, here is an example
public Constructor()
{
Value = PopulateValueFromDB(); //async method
CalculateInDB(); // async method
}
public async Task<string> PopulateValueFromDB()
{
... do some async calls
return await ...
}
public async Task CalculateInDB()
{
...
return await ...
}
Basically in constructor i have an error, because i cannot use await there, and i cannot make it async.
For CalculateInDB i can make return it void, then i solve the issue with it, although i read somewhere that returning void is not very good solution.
Regarding the PopulateVlaue method ...i have to return something ...
So is there a work around ir i shouldn't use those methods then and make them sync instead of async?
I have a blog post on async constructors that covers a variety of approaches. If possible, I recommend you use the factory pattern, as such:
private Constructor()
{
}
private async Task InitializeAsync()
{
Value = await PopulateValueFromDBAsync();
await CalculateInDBAsync();
}
public static async Task<Constructor> Create()
{
var ret = new Constructor();
await ret.InitializeAsync();
return ret;
}
This is a time to use old tech!
ThreadPool.QueueUserWorkItem.
Cheers -

Metro - write async c# operation and call from javascript

I have create a metro app which is composed by
- a c# windows runtime component
- a javascript application, wich contains the UI and is the main application.
In the c# component I created an async method:
async public void createDocument() {
}
but when I try to call it from the javascript code, I cannot use the .done() or the then() function to handle the method completed evet, because there is an error: javascript error, cannot call done() from object not set to an instance of object.
If I try to assign Task or Task to the function I have another error, which tell me Task is not a windows runtime type and to use IAsyncOperation, IAsyncAction, ecc.. instead.
So, how can I create an async function in the c# windows runtime component and call it from javascript handling the done() or then() events?
I found an article that seems to be related to the problem you are having. I haven't done this myself, but the gist of it says that you can't use the async keyword from C# for Javascript promises - you must wrap the method in a slightly different way:
instead of:
public sealed class Class1
{
public async void testAsync()
{
// do this asynchronously ...
}
}
try:
public sealed class Class1
{
public IAsyncActionWithProgress<Result> testAsync()
{
return AsyncInfo.Run<Result>((token, result) =>
Task.Run<Result>(()=>
{
// do this asynchronously ...
return new Result();
}
));
}
}
public sealed class Result { ... }
}
I copied and pasted the examples from this article by Ronald Widha - http://www.ronaldwidha.net/2012/05/10/winrt-consumer-preview-calling-c-csharp-async-class-libraries-from-javascript-winjs-promises-using-then-clause/ It was written during the consumer preview, so it might have changed between then and the final release
Hopefully that will help you a bit more!
Just for information, if you need to call asyncronous methods inside the procedure, you need to use:
public static IAsyncOperation<IList<string>> DownloadAsStringsAsync(string id)
{
return Task.Run<Type retourned>(async () =>
{
var data = await AsyncMethod(...);
return (somethingOfTypeRetourned;
}).AsAsyncOperation();
}

Categories