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?
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.
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!
In . NET, Task. Run is used to asynchronously execute CPU-bound code.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With