When to return task over using async - c#

I am abit confused when it comes to how a method should look like when dealing with async / task.
From my understanding, a method that just creates a new task doesnt need to be async since this would produce overhead as it wraps the hole thing in a new task.
So this:
async Task _doStuff()
{
await Task.Run(()=> _stuff());
}
Is better this way:
Task _doStuff()
{
return Task.Run(()=> _stuff());
}
However, it gets a bit more complicated, if there are some preconditionchecks
Which way is better then?
async Task _doStuff()
{
if(stuffWasDone)
return;
await Task.Run(()=> _stuff());
}
or
Task _doStuff()
{
if(stuffWasDone)
return Task.Run(()=> {}); // this could be a static-readonly in some helper like AsyncHelper.Empty(); as there is no FromResult for Task.
return Task.Run(()=> _stuff());
}

You dont have to use Task.Run in order to generate a Task. A Task is a promise.
If a Task doesn't need to execute, don't create one. Using Task.Run has the overhead of invoking an empty lambda on a threadpool thread, you don't need that. Simply returning should suffice.
You may also use Task.FromResult if no Task is actually needed:
Task DoStuffAsync()
{
if(stuffWasDone)
{
return Task.FromResult(0);
}
return Task.Run(() => _stuff());
}
If you don't want to re-generate the Task over again, you can simply put it in a local variable:
private static Task _emptyTask = Task.FromResult(0);
As for your first example of await vs return await, you cannot say one is "better" then the other, as they serve different purposes. The former will asynchronously wait for the Task to complete before returning while the latter will return a hot task to the caller. This will matter in regards of exception handling. More so, if you're not going to be consuming the result of the task afterwards, using await will incur in a redundant generation of a state machine.
As another side note, wrapping synchronous methods in asynchronous wrappers is bad practice. Let the end user explicitly call Task.Run instead, don't fool them with async behavior.

Related

C# Task.Delay(1).Wait() deadlocks but only if inside another Task [duplicate]

I don't quite understand the difference between Task.Wait and await.
I have something similar to the following functions in a ASP.NET WebAPI service:
public class TestController : ApiController
{
public static async Task<string> Foo()
{
await Task.Delay(1).ConfigureAwait(false);
return "";
}
public async static Task<string> Bar()
{
return await Foo();
}
public async static Task<string> Ros()
{
return await Bar();
}
// GET api/test
public IEnumerable<string> Get()
{
Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray());
return new string[] { "value1", "value2" }; // This will never execute
}
}
Where Get will deadlock.
What could cause this? Why doesn't this cause a problem when I use a blocking wait rather than await Task.Delay?
Wait and await - while similar conceptually - are actually completely different.
Wait will synchronously block until the task completes. So the current thread is literally blocked waiting for the task to complete. As a general rule, you should use "async all the way down"; that is, don't block on async code. On my blog, I go into the details of how blocking in asynchronous code causes deadlock.
await will asynchronously wait until the task completes. This means the current method is "paused" (its state is captured) and the method returns an incomplete task to its caller. Later, when the await expression completes, the remainder of the method is scheduled as a continuation.
You also mentioned a "cooperative block", by which I assume you mean a task that you're Waiting on may execute on the waiting thread. There are situations where this can happen, but it's an optimization. There are many situations where it can't happen, like if the task is for another scheduler, or if it's already started or if it's a non-code task (such as in your code example: Wait cannot execute the Delay task inline because there's no code for it).
You may find my async / await intro helpful.
Based on what I read from different sources:
An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.
To wait for a single task to complete, you can call its Task.Wait method. A call to the Wait method blocks the calling thread until the single class instance has completed execution. The parameterless Wait() method is used to wait unconditionally until a task completes. The task simulates work by calling the Thread.Sleep method to sleep for two seconds.
This article is also a good read.
Some important facts were not given in other answers:
async/await is more complex at CIL level and thus costs memory and CPU time.
Any task can be canceled if the waiting time is unacceptable.
In the case of async/await we do not have a handler for such a task to cancel it or monitoring it.
Using Task is more flexible than async/await.
Any sync functionality can by wrapped by async.
public async Task<ActionResult> DoAsync(long id)
{
return await Task.Run(() => { return DoSync(id); } );
}
async/await generate many problems. We do not know if await statement will be reached without runtime and context debugging. If first await is not reached, everything is blocked. Sometimes even when await seems to be reached, still everything is blocked:
https://github.com/dotnet/runtime/issues/36063
I do not see why I must live with the code duplication for sync and async method or using hacks.
Conclusion: Creating Tasks manually and controlling them is much better. Handler to Task gives more control. We can monitor Tasks and manage them:
https://github.com/lsmolinski/MonitoredQueueBackgroundWorkItem
Sorry for my english.

Is awaiting methods from synchronous sources with await Task.Run(() => good practice?

I have a method that has the async keyword with a task. This method returns a string that comes from JwtSecurityTokenHandler().WriteToken(t); The thing is none of the assignments in the body of the method are awaitable.I get the warning CS-1998. That says you shouldnt use async for synchronous methods which makes complete sense. But then it adds that you can use await Task.Run(() => { . So is it good practice to do this?
public async Task<object> GenerateMyUserJwtToken(string email, IdentityUser user)
//code that isnt awaitable
{
var u = await Task.Run(() =>
{
return new JwtSecurityTokenHandler().WriteToken(token);
});
return u;
}
edit: I did not ask what the error was I asked if it was a good idea to Implement await Task.Run(() on an async method signature that has no await assignments. I also asked that another async method is awaiting this in the another method here is the code
//awaiting method:
public async Task<object> LoginAsync(LoginDto model)
{
return await GenerateMyUserJwtToken(model.Email, appUser);
}
//controller:
[HttpPost("login")]
public async Task<object> Login([FromBody] LoginDto model)
{
var logMeIn = await new AuthUserService().LoginAsync(model);
return logMeIn; //returns token
}
My Question is is this async all the way or does the task.Run stop that process?
Using Task.Run just to make something sync is generally a bad practice but it cannot be stated generally.
If the sync method to execute may take for a long time, then it can be a solution. Please note that Task.Run will assign the task to a pool thread and it is not always desirable. It is a common misunderstanding that async methods always use or should use threads somewhere at the end of the async-await chain. However, async-await has nothing to do with threads, it is about asynchronicity (chaining deferred tasks) and creating threads is just one option to create awaitable tasks.
So what are the options?
The method to call is fast and never blocks the caller for long time (>100ms or so): do not use async at all. In this case Task<T>.FromResult(result) is a tempting solution but is highly discouraged because it is misleading for the caller. Use it only in unit tests or if you are forced to implement an async method of an interface you cannot change.
The method execution takes for a long time because it is CPU bound: now you can use a thread. But I typically would not use pool threads for long lasting tasks as it can cause nasty side effects if the thread pool is out of threads. Use await Task.Factory.StartNew(() => MyLongRunningTask(), cancellationToken, TaskCreationOptions.LongRunning); instead, which creates a brand new thread instead of bothering the pool.
The method execution takes for a long time because it is IO bound (eg. sending/receiving packets via a hardware): Use TaskCompletitionSource<T>, add a hook to the whatever completition event of the device (eg. OS hook or IRQ notification) and from that set the result of the completition source and return its task.

Making async method properly

I googled a lot and for the moment the only async implementation I found (including MSDN site) is the following:
public async void Foo()
{
...
await StreamReader.ReadAsync();
...
}
So in all the cases they use some method which is already async. And this is not what I need.
Let's say that I have a heavy method that does something:
public void DoSomthing()
{
...
}
And there is method where I call this DoSomething:
public void MajorMethod()
{
DoSomething();
}
I want to make DoSomething ayncthonous and call it.
The only solution I see would be the following one:
public Task MajorMethod()
{
return Task.Run(()=>DoSomething());
}
But I read some comments that it's not really the async. So how can I make DoSomething async?
If the MajorMethod has no other things to do other than calling the DoSomething, your code is fine.
But if you need to do other stuff after calling to DoSomething, then mark MajorMethod as async, and use await before Task.Run
public async Task MajorMethod()
{
await Task.Run(()=>DoSomething());
//stuff in here will executed after DoSomething completed
}
Examples from MSDN: Asynchronous programming
or just google c# async
You should be clear about the role async/await play in the Task Asynchronous Pattern. Making an async method does not parform an operation asynchronously just like that. Marking an existing method async will not magically perform everything in there asynchronously. Its main effect is that now you are allowed to use await within the method (I read that it even was discussed if the async keyword was necessary at all; it was added to avoid a breaking change when a local variable in existing methods would be named await).
await also does not provide asynchrony by itself, it provides a way to synchronize to another asnychronous method and yield while the other operation is still running. You can await another async method, but unless somwhere down the chain there is an actual Task running in another thread, the async method might even return synchronously.
In consequence this means that you need an operation that runs asynchronously first (such as a DB query, file access, network communication) and from there you create a chain of async methods that await the previous method.
Now in your case, when you have a computationally intensive method that does not wait for external resources, you can choose to perform the operation asynchronously. Since modern CPUs usually have more than one core at your disposal, you can increase both, performance and application responsiveness like that. The method would not be async, since it does not await anything:
void DoSomething()
{
//...
}
Task DoSomethingAsync() {
return Task.Run(DoSomething);
}
All callers of DoSomethingAsync can now use await to synchronize with this operation running in the background (note the change in return type to Task to allow callers to await):
async Task MajorMethod() {
//...
await DoSomethingAsync();
//...
}
This would allow callers of MajorMethod to synchronize with it. What you can also do is to do stuff in MajorMethod while DoSomethingAsync is running (and still await to allow callers to do even more parallel operations):
async Task MajorMethod() {
//This part will run before DoSomethingAsync
//...
Task doSomethingTask = DoSomethingAsync();
//This part is executed at the same time as DoSomethingAsync
//...
await doSomethingTask; //Here the caller can do more operations while DoSomething is running
//This part will be executed after DoSomethingAsync has finished
//...
}
This form of acquiring a task, doing something and only then awaiting the task has to be done somewhere in the chain, otherwise you have no benefit from the asynchronous operation. Even though this might be an overgeneralization, since synchronization can happen in more subtle ways, for example with a custom synchronization context. But as far as your question is concerned, you should go with: There is an actual task on one end and something that is done after the async call, but before the await on the other end.

How to create a Task of an async Task method to catch the exceptions?

I have a task that is looping reading on a socket:
private async void readLoop() {
while (!cts.IsCancelRequested()) {
await socket.ReceiveAsync(data, ...);
doWork(data);
}
}
And since the task need not run as soon as it is created, I'm using the Task constructor, rather than Task.Run.
private Task readTask = new Task(readLoop, cts, LongRunning);
// when the task need to run:
readTask.Start()
At this point it works fine, except that when the task need to finish, when I call readTask.Wait() or await readTask, the exceptions happened in ReceiveAsync or doWork are not attached to the readTask. That means even there was exceptions, readTask.Status is RunToComplete and readTask.Exception is null. Accord. to the docs, this is due to the async method returns void, but when I tried this:
private async Task readLoop() {...}
It won't compile:
error CS0407: 'Task WebSocketInitiator.readLoop()' has the wrong return type
So is there anyway to make the task start at a later time and at the same time have it keep track of exceptions happened in the task?
A minimal test case to show the problem: https://dotnetfiddle.net/JIfDIn
If I understand you correctly you want to postpone running the Task until it is needed but you want to keep the creation in a constructor. That is fine, and there is a pattern used for these kind of situations. It's called Lazy.
However, Lazy isn't async. Stephen Taub has however made an async implementation called AsyncLazy.
The reason why you got the error message that you got was because you didn't specify the return value for the outer Task that you created. Also you need to return foos value. If you wrap the call in a lambda which returns the inner Task you can get it though, as such:
var task1 = new Task<Task>(async () => await foo(),
CancellationToken.None, TaskCreationOptions.LongRunning);
task1.Start();
When you await it however you would await the outer task and not the task that it returns. Thus you need to Unwrap it:
task1.Unwrap().Wait();
This way you would catch the exception. However, this is probably not the best way, since the whole reason to use Task.Run, async and await was to avoid these constructs.
In conclusion:
Go for AsyncLazy if you need to postpone the calling of your Task
Don't call the Task constructor
Use Task.Run
And since the task need not run as soon as it is created, I'm using the Task constructor, rather than Task.Run.
You should never use the task constructor. It has literally no rational use cases at all.
In your case, it sounds like you don't need a delegate or lazy-initialization, or anything like that; since your members and methods are private, it would make just as much sense to assign the task member at the time it executes:
private async Task readLoop();
// when the task needs to run:
readTask = Task.Run(() => readLoop());
However, if you do need to represent some code to run in the future and not now, then you want a delegate. In this case, an asynchronous delegate: Func<Task>:
Func<Task> func = () => Task.Run(() => readLoop());
...
Task task = func();

Difference in task processing

Let's suppose that I Have two methods, like this...
public void MyMethod()
{
// do some stuff
}
public Task MyMethodAsync()
{
//run MyMethod asynchronously
}
What is the best form to execute it in async way?
Like this
public Task MyMethodAsync()
{
return Task.Run(() => MyMethod());
}
or like this?
public async Task MyMethodAsync()
{
await Task.Run(() => MyMethod());
}
You should read Stephen Cleary's tutorial on when -- and when not -- to use Task.Run.
Short answer: don't use Task.Run to create a fake async method. If your code isn't truly async, then let the caller decide if it should use a thread (or whatever) to call your code.
In the case of your first method, you may as well just have a task on a separate thread. It's not really async because you aren't clearly waiting for the thread to end to start a new process. If you called this it would continue before the task was complete.
public Task MyMethodAsync()
{
return Task.Run(() => MyMethod());
}
Looking at the second version. You are waiting for the task to complete so that you can do something after without holding up the current thread.
public async Task MyMethodAsync()
{
await Task.Run(() => MyMethod());
DoMoreWork();
//Do something following the completion of the task
//without binding up the calling thread, but actually complete it on that thread.
}
It's better to go the other way around. Build the inner task as async, and then let all the callers who can't use the async method use the async one internally and wait on it.
public void MyMethod()
{
MyMethodAsync().Wait();
}
public async Task MyMethodAsync()
{
// do some stuff
}
Both of your methods aren't truly making anything async. Async isn't about running something in the background, that's the realm of the Task library (or parallel extensions, or threading, etc). Async is about being able to re-use a single thread for multiple things when it has nothing better to do -- which makes thing more scalable. Making a pseudo-async method is just hiding the fact that you are using a NEW thread instead of reusing the same thread, which makes the system LESS scalable.
In order to do that, true async processes need to be written that way from the inside out. Everything (or at least the parts that are time consuming) need to rely on async methods that do that. For example, making a SOAP call where the thread is going to basically just sit idle while waiting for the call to return, or a database call, or file I/O. Async allows that thread to go do something else useful instead of just sitting idle.

Categories