Why Do I Need To Make This Method Async? [duplicate] - c#

This question already has answers here:
How does Task<int> become an int?
(2 answers)
Closed 7 years ago.
I've got code very similar to this (I've simplified the code a bit to demonstrate the essence of the behavior I'm trying to figure out).
public async System.Threading.Tasks.Task<bool> IsNumberOdd(int numToTest)
{
if (numToTest % 2 == 0)
{
return false;
}
else
{
return true;
}
}
If I leave off the async keyword, I get a complaint about not being able to cast a bool to a Task<bool>. I'm assuming there's some syntactic sugar involved here. Looking at the IL (I'm not super familiar with IL) it seems as if the async keyword is causing the task to be run and then the return value is the result of the task. Am I understanding this correctly?
By the way, if this is a dupe or if there's some blog posting that discusses this, feel free to point me to it and close this up. I'm not trying to pad my rep; I'm trying to understand what's going on with this code.
EDIT:
For all those who were asking "why is this method async?"--because I was trying to build a small and simple code example to demonstrate the question. I should have also added an example of the calling code but I was trying to keep the code as small and simple as I could.

I'm assuming there's some syntactic sugar involved here
Not exactly "syntactic sugar". The compiler is generating a state-machine as the method was marked as async. That is why you can return a Task<bool> without explicitly creating a Task for the return value.
If I leave off the async keyword, I get a complaint about not being
able to cast a bool to a Task<bool>.
The async modifier is what triggers the compiler to create the state machine. If you remove it, you'll need to create the Task yourself. If for any reason you want to create a Task<T> but you're actually running synchronously, Task.FromResult is your friend.
I see no reason why this method is marked async.

it seems as if the async keyword is causing the task to be run and then the return value is the result of the task
Correct.
There is nothing in this method that would benefit from it being async. However:
If I leave off the async keyword, I get a complaint about not being able to cast a bool to a Task<bool>
Would be happening in the caller. Without seeing that code one can only comment generally that you can either:
Change the caller to not assume it is getting a waitable return.
Change the function to return bool, but on the caller use Task.FromResult(IsNumberOdd(value)).

It's not about the async. Its about the Task.
your returning a bool and the return value of your function is Task
public Task<bool> DoSomething()
{
return false;
}
will also not compile.
if your not doing any thing asynchronous you shouldn't return a Task.
If you need to run something asynchronously , here are a few options which i hope will make the usage of async/await clearer.
public class Sample
{
public async void RunSample()
{
// return a task. later obtain a result if some fashion
Task<bool> task = DoSomethingAsync();
bool res1 = task.Result;
// await a task which is created for you by re-wrapping the result.
bool res2 = await AwaitSomethingAsync();
// await a task which is created for you by rewrapping the result due to await.
bool res3 = await DoSomethingAsync2();
// await a task.
bool res4 = await DoSomethingAsync();
}
public async Task<bool> DoSomethingAsync2()
{
return false;
}
public Task<bool> DoSomethingAsync()
{
return Task<bool>.Run(() => { return false; });
}
public async Task<bool> AwaitSomethingAsync()
{
bool res = await Task<bool>.Run(() => { return false; });
return res; // re-wraps it in a Task
}
}

Related

C# Difference between Task.Run(() =>) and Task.Run(async() => await) [duplicate]

Is there any scenario where writing method like this:
public async Task<SomeResult> DoSomethingAsync()
{
// Some synchronous code might or might not be here... //
return await DoAnotherThingAsync();
}
instead of this:
public Task<SomeResult> DoSomethingAsync()
{
// Some synchronous code might or might not be here... //
return DoAnotherThingAsync();
}
would make sense?
Why use return await construct when you can directly return Task<T> from the inner DoAnotherThingAsync() invocation?
I see code with return await in so many places, I think I might have missed something. But as far as I understand, not using async/await keywords in this case and directly returning the Task would be functionally equivalent. Why add additional overhead of additional await layer?
There is one sneaky case when return in normal method and return await in async method behave differently: when combined with using (or, more generally, any return await in a try block).
Consider these two versions of a method:
Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return foo.DoAnotherThingAsync();
}
}
async Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return await foo.DoAnotherThingAsync();
}
}
The first method will Dispose() the Foo object as soon as the DoAnotherThingAsync() method returns, which is likely long before it actually completes. This means the first version is probably buggy (because Foo is disposed too soon), while the second version will work fine.
If you don't need async (i.e., you can return the Task directly), then don't use async.
There are some situations where return await is useful, like if you have two asynchronous operations to do:
var intermediate = await FirstAsync();
return await SecondAwait(intermediate);
For more on async performance, see Stephen Toub's MSDN article and video on the topic.
Update: I've written a blog post that goes into much more detail.
The only reason you'd want to do it is if there is some other await in the earlier code, or if you're in some way manipulating the result before returning it. Another way in which that might be happening is through a try/catch that changes how exceptions are handled. If you aren't doing any of that then you're right, there's no reason to add the overhead of making the method async.
Another case you may need to await the result is this one:
async Task<IFoo> GetIFooAsync()
{
return await GetFooAsync();
}
async Task<Foo> GetFooAsync()
{
var foo = await CreateFooAsync();
await foo.InitializeAsync();
return foo;
}
In this case, GetIFooAsync() must await the result of GetFooAsync because the type of T is different between the two methods and Task<Foo> is not directly assignable to Task<IFoo>. But if you await the result, it just becomes Foo which is directly assignable to IFoo. Then the async method just repackages the result inside Task<IFoo> and away you go.
If you won't use return await you could ruin your stack trace while debugging or when it's printed in the logs on exceptions.
When you return the task, the method fulfilled its purpose and it's out of the call stack.
When you use return await you're leaving it in the call stack.
For example:
Call stack when using await:
A awaiting the task from B => B awaiting the task from C
Call stack when not using await:
A awaiting the task from C, which B has returned.
Making the otherwise simple "thunk" method async creates an async state machine in memory whereas the non-async one doesn't. While that can often point folks at using the non-async version because it's more efficient (which is true) it also means that in the event of a hang, you have no evidence that that method is involved in the "return/continuation stack" which sometimes makes it more difficult to understand the hang.
So yes, when perf isn't critical (and it usually isn't) I'll throw async on all these thunk methods so that I have the async state machine to help me diagnose hangs later, and also to help ensure that if those thunk methods ever evolve over time, they'll be sure to return faulted tasks instead of throw.
This also confuses me and I feel that the previous answers overlooked your actual question:
Why use return await construct when you can directly return Task from the inner DoAnotherThingAsync() invocation?
Well sometimes you actually want a Task<SomeType>, but most time you actually want an instance of SomeType, that is, the result from the task.
From your code:
async Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return await foo.DoAnotherThingAsync();
}
}
A person unfamiliar with the syntax (me, for example) might think that this method should return a Task<SomeResult>, but since it is marked with async, it means that its actual return type is SomeResult.
If you just use return foo.DoAnotherThingAsync(), you'd be returning a Task, which wouldn't compile. The correct way is to return the result of the task, so the return await.
Another reason for why you may want to return await: The await syntax lets you avoid hitting a mismatch between Task<T> and ValueTask<T> types. For example, the code below works even though SubTask method returns Task<T> but its caller returns ValueTask<T>.
async Task<T> SubTask()
{
...
}
async ValueTask<T> DoSomething()
{
await UnimportantTask();
return await SubTask();
}
If you skip await on the DoSomething() line, you'll get a compiler error CS0029:
Cannot implicitly convert type 'System.Threading.Tasks.Task<BlaBla>' to 'System.Threading.Tasks.ValueTask<BlaBla>'.
You'll get CS0030 too, if you try to explicitly typecast it.
This is .NET Framework, by the way. I can totally foresee a comment saying "that's fixed in .NET hypothetical_version", I haven't tested it. :)
Another problem with non-await method is sometimes you cannot implicitly cast the return type, especially with Task<IEnumerable<T>>:
async Task<List<string>> GetListAsync(string foo) => new();
// This method works
async Task<IEnumerable<string>> GetMyList() => await GetListAsync("myFoo");
// This won't work
Task<IEnumerable<string>> GetMyListNoAsync() => GetListAsync("myFoo");
The error:
Cannot implicitly convert type 'System.Threading.Tasks.Task<System.Collections.Generic.List>' to 'System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable>'

What is the right approach with Async/Await/Task on function overloading in C# [duplicate]

This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
Closed 3 years ago.
I have a function:
public static async Task DoSomthing(string str1, int num1, bool bool1)
{
//Do something.... (This function will not return any value)
}
I want to overload this function so it can be called with other arguments, but this function will basically call the function above.
Now I have 2 choices and I don't know what is the better one (in every aspect from performance to good coding)?
Option 1:
public static Task DoSomething(CustomObject obj)
{
return DoSomthing(obj.str, obj.num1, obj.bool1);
}
Option 2:
public static async Task DoSomething(CustomObject obj)
{
await DoSomthing(obj.str, obj.num1, obj.bool1);
}
It will be executed almost in the same way but for the one with await it will add some overhead because the compiler will create a state machine.
Compiler creates state machine for methods with async-await keywords so when the control flow reaches await it is returned to the calling method. The execution of async method continues when the awaited Task (or method that returns Task) has finished execution.
As there is no code after await it is somewhat inadvisable to use await in this scenario. You could simply return a Task.
You can do option 1 because you only want to return the task witch it's passing.
Personally I prefer to read in the Taskname Async like DoSomthingAsync you you always know what's async and what's sync
public static Task DoSomethingAsync(CustomObject obj)
// or set the ConfigureAwait to true when you need stuff done on the same thread.
=> DoSomthingAsync(obj.str, obj.num1, obj.bool1).ConfigureAwait(false);

Can't method chain with async/await

I have an ASP.NET app running on .NET 4.6.1.
I can't use .Sum() on my awaited GetInts() result. The compiler thinks that GetInts() is a task. SumIntsOneLinerBroker() doesn't compile.
public Task<List<int>> GetInts() {
var list = new List<int> { 4, 5 };
return Task.FromResult(list);
}
public async Task<int> SumInts() {
var ints = await GetInts();
return ints.Sum();
}
public async Task<int> SumIntsOneLinerBroker() {
return await GetInts().Sum();
}
public async Task<int> SumIntsOneLinerWorking() {
return (await GetInts()).Sum();
}
There are a few ways of handling this. The most common is probably the parentheses that you show in your code and confirmed by Marc.
An alternative is .ContinueWith which lets you pass the result of the first operation to the second. Here's a Microsoft Example. Keep in mind, when you utilize ContinueWith, exceptions will get wrapped in an AggregateException, which can alter your exception handling.
Confirmed by Marc, the parentheses enclosing method as seen in the second image is the proper approach. Nothing to see here.

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 handle return values in async function

When working on data APIs which use async rest calls (I am using RestSharp.Portable), what is the best way to handle return values? Since async function can only return a Task or Task ... but the caller has no way to getting back to the return value ... how would the API return data back to the caller? Global properties?
From what I have read so far, it appears that callback functions are the only way to interact with Response Data?
Take the following method for example; previously I was not using async Rest library and was able to return a value but after converting it to use RestSharp.Portable, I dont see a way to return the value:
public async Task<EntityResourceDescriptor> GetEntityDescriptor(string entityType)
{
TaskCompletionSource<EntityResourceDescriptor> tcs = new TaskCompletionSource<EntityResourceDescriptor>();
var req = new RestRequest("/qcbin/rest/domains/{domain}/projects/{project}/customization/entities/{entityType}");
AddDomainAndProject(req);
req.AddParameter("entityType", entityType, ParameterType.UrlSegment);
client.ExecuteAsync<EntityResourceDescriptor>(req, (res) =>
{
if (res.ResponseStatus == ResponseStatus.Error)
{
tcs.TrySetException(res.ErrorException);
}
else
{
tcs.SetResult(res.Data);
}
}
);
return tcs.Task;
}
Here all I can do is return Task but the caller still has no way to get to the response data or am I missing something obvious? Can the caller subscribe to an event which gets fired at Task.Completed etc.?
I am very fuzzy on this async concept. Are there any examples of writing Portable data APIs?
I think you'll really need to take a step back and read about how to use the async and await keywords. Among other things, you'll need to understand some of the compiler magic that happens behind the scenes when coding async methods.
Here is a good place to start: Asynchronous Programming with Async and Await.
More to your question, the Return Types and Parameters section has this to say:
You specify Task<TResult> as the return type if the method contains a Return (Visual Basic) or return (C#) statement that specifies an operand of type TResult.
It then gives the following code example:
// Signature specifies Task<TResult>
async Task<int> TaskOfTResult_MethodAsync()
{
int hours;
// . . .
// Return statement specifies an integer result.
return hours;
}
Notice how despite the method return type of Task<int>, the return statement simply returns an int, not a Task<int>. That's basically because there is some compiler magic going on that makes this legal only in async methods.
Without wanting to get into all the details, you should also know that the caller of the async method is normally expected to do so using the await keyword, which knows how to deal with the Task or Task<TResult> return values and automatically unwraps the actual expected return value for you in a transparent manner (more compiler magic behind the scenes).
So for the above example, here is one way to call it:
int intValue = await TaskOfTResult_MethodAsync(); // Task<int> is automatically unwrapped to an int by the await keyword when the async method completes.
Or, if you wish to start the async method, perform some other work in the meantime, and then wait for the async method to complete, this can be done like this:
Task<int> t = TaskOfTResult_MethodAsync();
// perform other work here
int intValue = await t; // wait for TaskOfTResult_MethodAsync to complete before continuing.
Hopefully this gives you a general idea of how to pass values back from an async method.
For your specific example, I am not familiar with RestSharp (never used it). But from what little I read, I think you'll want to use client.ExecuteTaskAsync<T>(request) instead of client.ExecuteAsync<T>(request, callback) to better fit in the async-await model.
I'm thinking your method would instead look something like this:
public async Task<EntityResourceDescriptor> GetEntityDescriptor(string entityType)
{
var req = new RestRequest("/qcbin/rest/domains/{domain}/projects/{project}/customization/entities/{entityType}");
AddDomainAndProject(req);
req.AddParameter("entityType", entityType, ParameterType.UrlSegment);
var res = await client.ExecuteTaskAsync<EntityResourceDescriptor>(req);
if (res.ResponseStatus == ResponseStatus.Error)
{
throw new Exception("rethrowing", res.ErrorException);
}
else
{
return res.Data;
}
}
Your calling code would then look like this:
EntityResourceDescriptor erd = await GetEntityDescriptor("entityType");
I hope you manage to get this working. But again, make sure to read the documentation about the async-await style of programming. It's very neat once you wrap your head around the compiler magic that is done for you. But it's so easy to get lost if you don't take the time to really understand how it works.

Categories