Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task.FromResult() vs. Task.Run()

I've come across quite a few situations lately where async methods execute synchronously, but return a Task anyway, so they can be awaited, e.g.

public virtual Task CreateAsync(TUser user) {     ThrowIfDisposed();     if (user == null) throw new ArgumentNullException("user");     Context.Save(user);     Context.Flush();     return Task.FromResult(0); } 

Surely it is better to dispatch the probably-long-running operation to a thread and return the still active task, to genuinely be awaited:

public virtual Task CreateAsync(TUser user) {     ThrowIfDisposed();     if (user == null) throw new ArgumentNullException("user");     return Task.Run(() =>     {         Context.Save(user);         Context.Flush();     }); } 

I some suspicion, though, that just spinning off TPL threads isn't the safest practice. Any commentary on these two different patterns?

like image 541
ProfK Avatar asked Nov 30 '15 18:11

ProfK


People also ask

Should you use task FromResult?

This method is useful when you perform an asynchronous operation that returns a Task object, and the result of that Task object is already computed. Show activity on this post. Use the Task. FromResult when you want to have a asynchronous operation but sometimes the result is in hand synchronously.

What is the difference between task run and Task start?

Now, let's talk about the difference from the TaskScheduler context. Task. Run(action) internally uses the default TaskScheduler , which means it always offloads a task to the thread pool. StartNew(action) , on the other hand, uses the scheduler of the current thread which may not use thread pool at all!

What does Task run () do?

In . NET, Task. Run is used to asynchronously execute CPU-bound code.

What does await task FromResult do?

FromResult means someone needs a task, but I already have the result of that task, so make a task that is already complete. When it is await ed or when Result is called on it, either way, it returns the result immediately.


2 Answers

If your method is synchronous you shouldn't return a Task to begin with. Just create a traditional synchronous method.

If for some reason that's not possible (for example, you implement some async interface) returning a completed task using Task.FromResult or even better in this case Task.CompletedTask (added in .NET 4.6) is much better than using Task.Run in the implementation:

public virtual Task CreateAsync(TUser user) {     // ...     return Task.CompletedTask; } 

If the consumer of your API cares strongly about the Task-returning method not running synchronously they can use Task.Run themselves to make sure.

You should keep in mind that async methods may have a considerable synchronous part (the part before the first await) even if they do eventually continue asynchronously. You can't assume async methods return a Task immediately anyway.

like image 121
i3arnon Avatar answered Sep 19 '22 10:09

i3arnon


Task.FromResult doesn't actually creates or runs a task but it just wraps the returned result in a task object. I personally used it in Unit Tests where I need to simulate the Async methods and Of course I wouldn't want to run actual tasks in Unit tests.

Besides Task.Run will actually create a task and run a task on TaskScheduler. It is not recommended to use Task.Run when you're doing Async programming. Rather use await on tasks. See few do's and don't of Tasks by Stephen Cleary.

like image 38
vendettamit Avatar answered Sep 22 '22 10:09

vendettamit