Creating an typed async Task - c#

I want to create some async Tasks without starting them at the moment.
With the untyped Tasks there is no problem:
private Task CreateTask() {
return new Task(
async () => await DoSomething().ConfigureAwait(false));
}
But to handle Exceptions I added a return value to my function. But how can I write it in a correct syntax:
private Task<bool> CreateTask() {
return new Task<bool>(
async () => await DoSomething().ConfigureAwait(false));
}
I get the message, that the async lambda expression can't be converted to func.
So my question: How is it written correctly?

I want to create some async Tasks without starting them at the moment.
That is the wrong solution for whatever problem you're trying to solve. If you want to define code that you want to run in the future, then you should use a delegate:
private Func<Task> CreateTaskFactory()
{
return async () => await DoSomething().ConfigureAwait(false);
}
But to handle Exceptions I added a return value to my function.
Again, that's not the best solution. Tasks already understand exceptions just fine without writing any additional code.
If you do need to return a value (as data), then you can return a delegate that creates a Task<T>:
private Func<Task<int>> CreateTaskFactory()
{
return async () => await DoSomethingReturningInt().ConfigureAwait(false);
}

Related

c#-WPF: Cannot convert async lambda expression to delegate type 'Func<int>'

Im trying to understand how Lambda expression work with async methods.
I have a function
private int Server_Get_Int(){
Task<int> task = Task.Factory.StartNew<int>( async () => {
FirebaseClient c = Server_Connect();
FirebaseResponse response = await c.GetAsync("todos/set");
return response.ResultAs<int>(); //The response will contain the data being retreived
} );
task.Wait();
int result = task.Result;
Console.WriteLine(result);
return result;
}
I want my async code to run in the lambda expression and get back the result from the server.
But i get back the error:
error CS4010: Cannot convert async lambda expression to delegate type 'Func<int>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'Func<int>'.
It says i can only return a void, task or task<> and to my understanding im returning
task<int>
Is this a problem with what im returning or is this because of async lambda?
Thanks
Edit:
response.ResultAs<int>()
Returns an Int but being inside a Task function it should be returned as a Task
Your whole method is suboptimal. You could rewrite your code to be much simpler. A few comments on your existing code first, however.
You're using Task.Factory.StartNew(), which is dangerous. In
most cases you should simply use Task.Run()
You're using Task.Wait() and Task.Result, which is also suboptimal, not to mention, that Task.Result includes Task.Wait() when accessing it. But I guess, that you want to test the lambda, so it's ok here.
The ResultAs<T>() method converts the response into an int (in your case). The method itself is defined as public virtual T ResultAs<T>(). It needn't return a Task<int>, because your lambda is asynchronous. If you'd remove the async from the lambda you'd have to return a Task<int>, but you can'T do that by simply changing the ResultAs<T> to ResultAs<Task<int>>, you'd have to use a TaskCompletionSource.
Based on the above that we can rewrite your method to this:
private int Server_Get_Int(){
var task = Task.Run(async () => {
var c = Server_Connect();
return (await c.GetAsync("todos/set")).ResultAs<int>();
});
int result = task.Result;
Console.WriteLine(result);
return result;
}
A more concise approach could look like this:
private async Task<int> Server_Get_Int_Async(){
return await Task.Run(async () => {
var c = Server_Connect();
return (await c.GetAsync("todos/set")).ResultAs<int>();
});
}
This creates a new task via Task.Run() and returns that to be completed later.
Based on the comments here are tow ways how you'd call the Server_Get_Int_Asnyc() method. I used explicit types so you can follow my comment, but in almost any case it's better to use var, because the compiler than can choose the best type for the job.
public async Task Foo()
{
// This is the fetch task that's going to be completed sometime in the future. You should almost in any case use configure await on your tasks. For reasons see below.
Task<int> intTask = Server_Get_Int_Async().ConfigureAwait(false);
// Do something other with the task object
// Finally await it and print
int result = await intTask;
Console.WriteLine(result);
}
// Do this if you just need the result and nothing else.
public async Task Bar()
{
int result = await Server_Get_Int_Async().ConfigureAwait(false);
Console.WriteLine(result);
}
In the end it seems, you're pretty new to Task based programming with async/await. I recommend you read the (excellent) introduction article written by Stephen Cleary and go on from there.
The beauty of async/await is, that it propagates naturally through your code and you can write asynchronous code almost like you'd write synchronous code.
Also, placing another article here on why you shouldn't use Wait() or Result to simply get the return value of the async method, since it's going to be noticed much better:
https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Test code (console app). This correctly shows "Result: 10".
static void Main(string[] args)
{
Func<Task<int>> func = async () => { await Task.Delay(1000); return 10; };
var task = Task.Factory.StartNew(func);
task.Wait();
int result = task.Unwrap().Result;
WriteLine($"Result: {result}");
ReadKey(true);
}

How to wait for async void to complete?

i need to wait for my async void to finish. It has some await Task.Delay functions in it and I need them to finish before it continues. This void doesn't return anything so I don't see a reason to make it async Task<> and I also shuffle an array inside this void and I declare some variables. So how can I do this ? Is async Task<> the only way ? My void is not expecting any parameters/inputs.
Return Task (not Task<T>) instead of void. Note, the non-generic form of Task does not need to wrap a value. It's just for signalling completion or errors, not results. In the case of async methods, this is equivalent to a synchronous void return type. It means you can wait for your method to complete.
Every async function should return Task instead of void and Task<TResult> instead of TResult. The only exception of this is the event handler.
So if your async function isn't an event handler it should return Task. Once this is done you can await for it...
... ehm, provided that your function is also declared async and returns Task or Task<TResult>, which makes that your clients all must be async.
If you have a sync function and want to call an async function use the following:
var myTask = Task.Run( () => SomeAsyncFunction(...));
// while my task is running you can do other things
// after a while you need the result:
Task.Wait();
// only if SomeAsyncFunction returns Task<TResult>:
TResult result = Task.Result();
Be aware though that this will halt your function until the task is finished. So when possible consider making your function also async. The code would be like:
public async void Button1_Clicked(object Sender, ...)
{
var task = MySlowMultiplier(3, 4);
// while task running you can do other things
// the UI remains responsive
// after a while:
int result = await task;
ProcessResult(result);
}
private async Task<int> MySlowMultiplier(int x, int y)
{
// I'm really slow:
await Task.Delay(TimeSpan.FromSeconds(5));
return x * y;
}
You can use this code.
var result = Task.Run(async() => { return await METHODNAMEHERE(); }).Result;

Passing a task as parameter

I am not sure whether this is possible, so here me out:
I have a sequence of action to perform multiple
async Task MethodA(...)
{
// some code
// a call to specific Async IO bound method
// some code
}
there are also MethodB(), MethodC(), etc, and all of the have exactly the same code, except for the call to specific Async IO bound method. I am trying to find a way to pass a task pointer to a method, so that we can execute it later in a Method().
What i am currently doing is this:
private async Task Method(Func<Task<Entity>> func)
{
// some code
var a = await task.Run(func);
// some code
}
var task = async () => await CallToIOBoundTask(params);
Method(task);
This code, however, pulls a new thread each time, which is not required for IO bound task, and should be avoided.
So, is there a way to refactor the code so that no ThreadPool thread is used? A goal is to have a code like this:
private async Task Method(Task<Entity> task)
{
// some code
var a = await task;
// some code
}
It is also important to mention that different IO calls have different method signatures. Also, a task can start to execute only in Method() body, and not before.
Of course, simply invoke the func, get back a task, and await it:
async Task Method(Func<Task<Entity>> func)
{
// some code
var a = await func();
// some code
}
Also, when you're sending that lambda expression, since all it's doing is calling an async method which in itself returns a task, it doesn't need to be async in itself:
Method(() => CallToIOBoundTask(params));
That's fine as long as all these calls return Task<Entity>. If not, you can only use Task (which means starting the operation and awaiting its completion) and you won't be able to use the result.

Wait for a void async method

How can I wait for a void async method to finish its job?
for example, I have a function like below:
async void LoadBlahBlah()
{
await blah();
...
}
now I want to make sure that everything has been loaded before continuing somewhere else.
Best practice is to mark function async void only if it is fire and forget method, if you want to await on, you should mark it as async Task.
In case if you still want to await, then wrap it like so await Task.Run(() => blah())
If you can change the signature of your function to async Task then you can use the code presented here
The best solution is to use async Task. You should avoid async void for several reasons, one of which is composability.
If the method cannot be made to return Task (e.g., it's an event handler), then you can use SemaphoreSlim to have the method signal when it is about to exit. Consider doing this in a finally block.
You don't really need to do anything manually, await keyword pauses the function execution until blah() returns.
private async void SomeFunction()
{
var x = await LoadBlahBlah(); <- Function is not paused
//rest of the code get's executed even if LoadBlahBlah() is still executing
}
private async Task<T> LoadBlahBlah()
{
await DoStuff(); <- function is paused
await DoMoreStuff();
}
T is type of object blah() returns
You can't really await a void function so LoadBlahBlah() cannot be void
I know this is an old question, but this is still a problem I keep walking into, and yet there is still no clear solution to do this correctly when using async/await in an async void signature method.
However, I noticed that .Wait() is working properly inside the void method.
and since async void and void have the same signature, you might need to do the following.
void LoadBlahBlah()
{
blah().Wait(); //this blocks
}
Confusingly enough async/await does not block on the next code.
async void LoadBlahBlah()
{
await blah(); //this does not block
}
When you decompile your code, my guess is that async void creates an internal Task (just like async Task), but since the signature does not support to return that internal Tasks
this means that internally the async void method will still be able to "await" internally async methods. but externally unable to know when the internal Task is complete.
So my conclusion is that async void is working as intended, and if you need feedback from the internal Task, then you need to use the async Task signature instead.
hopefully my rambling makes sense to anybody also looking for answers.
Edit:
I made some example code and decompiled it to see what is actually going on.
static async void Test()
{
await Task.Delay(5000);
}
static async Task TestAsync()
{
await Task.Delay(5000);
}
Turns into (edit: I know that the body code is not here but in the statemachines, but the statemachines was basically identical, so I didn't bother adding them)
private static void Test()
{
<Test>d__1 stateMachine = new <Test>d__1();
stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
stateMachine.<>1__state = -1;
AsyncVoidMethodBuilder <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
}
private static Task TestAsync()
{
<TestAsync>d__2 stateMachine = new <TestAsync>d__2();
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>1__state = -1;
AsyncTaskMethodBuilder <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
neither AsyncVoidMethodBuilder or AsyncTaskMethodBuilder actually have any code in the Start method that would hint of them to block, and would always run asynchronously after they are started.
meaning without the returning Task, there would be no way to check if it is complete.
as expected, it only starts the Task running async, and then it continues in the code.
and the async Task, first it starts the Task, and then it returns it.
so I guess my answer would be to never use async void, if you need to know when the task is done, that is what async Task is for.
do a AutoResetEvent, call the function then wait on AutoResetEvent and then set it inside async void when you know it is done.
You can also wait on a Task that returns from your void async
You can simply change the return type to Task and call await Task.CompletedTask at the end of the function, e.g:
async Task MyFunction() {
await AnotherFunction();
await Task.CompletedTask;
}
I find this simpler than wrapping the whole function body in a call to Task.Run(() => { ... });.
I've read all the solutions of the thread and it's really complicated... The easiest solution is to return something like a bool:
async bool LoadBlahBlah()
{
await blah();
return true;
}
It's not mandatory to store or chekc the return value. You can juste do:
await LoadBlahBlah();
... and you can return false if something goes wrong.

Why use async and await with Task<>?

If I have a normal method that I want to make asynchronous:
public int Foo(){}
I would do:
public Task<int> FooAsync(){
return Task.Run(() => Foo());
}
Why would I do:
public async Task<int> FooAsync(){
return await Task.Run(() => Foo());
}
The way I plan to use this is:
FooAsync().ContinueWith((res) => {});
I want the method to just run without stopping, but I want something like a callback to be fired, hence the ContinueWith. But with the second version, is there a point to using it?
In my understanding, you only need async and await when you write a method which does some async calls inside, but you would like it to look like it doesn't. In other words you want to write and read code as if it was some normal sequential code, handle exceptions as if it was normal sequential code, return values as if it was normal sequential code and so on. Then compiler's responsibility is to rewrite that code with all the necessary callbacks preserving the logic.
Your method is so simple I don't think it needs that rewriting at all, you can just return the task, but whoever consumes it may want to await for its return value.
Why would I do:
public async Task<int> FooAsync()
{
return await Task.Run(() => Foo());
}
You wouldn't. Your previous version returns Task which is already awaitable. This new version doesn't add anything.
The way I plan to use this is:
FooAsync().ContinueWith((res) => {});
I want the method to just run without stopping, but I want something like a callback to be fired, hence the ContinueWith.
This is where the difference comes in. Let's flesh out your example a little bit:
void DoAsyncStuff()
{
FooAsync().ContinueWith((res) => { DoSomethingWithInt(res.Result) });
}
Using async, you can write the same code like this:
void async DoAsyncStuff()
{
int res = await FooAsync();
DoSomethingWithInt(res);
}
The result is the same. The await keyword turns the rest of your method into a continuation which gets resumed after FooAsync produces a value. It's just like your other code, but easier to read. *shrug*

Categories