Create a completed TaskT
private readonly Result theResult = new Result();
public override Task<Result> StartSomeTask()
{
var taskSource = new TaskCompletionSource<Result>();
taskSource.SetResult(theResult);
return taskSource.Task;
}
Create a completed Task
The newest version of .Net (v4.6) is adding just that, a built-in Task.CompletedTask:
Task completedTask = Task.CompletedTask;
That property is implemented as a no-lock singleton so you would almost always be using the same completed task.
await Task.CompletedTask vs return
Let's look the question from the consumer-side.
If you define an interface, which imposes an operation that returns a Task
then you don't say anything about how it will be calculated / executed (so, there is no async
access modifier in the method signature). It is an implementation detail.
Interface
public interface ITest
{
Task Test();
Task<bool> IsTest();
}
So, it is up to you how you implement the interface.
You can do it in a synchronous way, when there won't be any AsyncStateMachine
generated because of the absence of the async
keyword.
Implementation #1
public class TestImpl : ITest
{
public Task Test()
{
return Task.CompletedTask;
}
public Task<bool> IsTest()
{
return Task.FromResult(true);
}
}
Or you can try to implement it in an asynchronous way but without await
operators. Here you will receive CS1998 warnings.
Implementation #2
public class TestImpl : ITest
{
public async Task Test()
{
return;
}
public async Task<bool> IsTest()
{
return true;
}
}
This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
In other words this implementation does not define a state machine. An async method is divided into different states based on the await
keywords:
- before_the_await_1,
- after_the_await_1_but_before_the_await_2
- after_the_await_2_but_before_the_await_3
- ...
If you haven't got any await then you would have a single state, which would run in sync (there is no need to preserve state, execute async operation and then call MoveNext()
).
Or you can try to implement it in an asynchronous way with await
operators.
Implementation #3
public class TestImpl : ITest
{
public async Task Test()
{
await Task.CompletedTask;
}
public async Task<bool> IsTest()
{
return await Task.FromResult(true);
}
}
In this case there will be an async state machine but it won't be allocated on the heap. By default it is a struct
and if it finishes in sync then we don't need to allocate them on the heap to extend its life out of the scope of the method.
For further information please read these articles:
- Async/await in .NET Core 3.x
- Async ValueTask Pooling in .NET 5
- Dissecting the async methods in C#
If my interface must return Task what is the best way to have a no-operation implementation?
Today, I would recommend using Task.CompletedTask to accomplish this.
Pre .net 4.6:
Using Task.FromResult(0)
or Task.FromResult<object>(null)
will incur less overhead than creating a Task
with a no-op expression. When creating a Task
with a result pre-determined, there is no scheduling overhead involved.
How does Task.CompletedTask work with thread pool?
the meaning of Task is to let a worker thread in the thread pool to run it,
Running code on the thread pool is one way in which Task
s manifest themselves.
Other ways to create Task
s are to write async
methods and to use Task.CompletedTask
1 or Task.FromResult<TResult>
2.
Just because Task.Run
causes code to run on the thread pool does not mean that these other uses of Task
must also necessarily involve the thread pool.
For Task.CompletedTask
, especially, this is "I've already done the work required, but I want to present it to other code as a Task
. No additional code runs anywhere.
We can see in the reference source that this property just returns the task:
/// <summary>A task that's already been completed successfully.</summary>
private static Task s_completedTask;
/// <summary>Gets a task that's already been completed successfully.</summary>
/// <remarks>May not always return the same instance.</remarks>
public static Task CompletedTask
{
get
{
var completedTask = s_completedTask;
if (completedTask == null)
s_completedTask = completedTask = new Task(false, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken)); // benign initialization ----
return completedTask;
}
}
1As shown in the reference source later though, we often aren't even creating a new Task
here, just reusing an existing one. But the team have obviously decided to forgo thread-safe initialisation of the property in favour of documenting that they won't guarantee to always return the same Task
.
2These latter two are quite similar, in that they represent "I've already done the work required, now for some reason I need to pass some other code a Task
"3.
3Often, and I'm guessing as is the case here, when you're implementing an interface or overriding a base class method that is Task
returning but your code is fast and synchronous so you have no need to be async
.
Why returning Task.CompletedTask failed to compile in an async method?
Your method could functionally be condensed down to this.
public static Task F()
{
return Task.Delay(1000);
}
Returning an Task.CompletedTask
instance is only useful if these apply:
- you do not want to use
async/await
- your method returns a Task (effectively
void
if you were to make it not asynchronous) - your code has logic where a task might not be returned
Example:
public static Task F()
{
if (someConditionToShortCircutTheMethod)
return Task.CompletedTask;
// rest of logic
return Task.Delay(1000);
}
As soon as you make your method async
then the fact that a Task is actually being returned is abstracted. This can make the code easier to work with especially if there are multiple points where the code waits for I/O operations to complete.
public static async Task F()
{
if (someConditionToShortCircutTheMethod)
return;
// rest of logic
await Task.Delay(1000);
await Task.Delay(1000);
// no return necessary, async Task has a similar flow as return type void
}
I also recommend reviewing these previous questions:
- How and when to use ‘async’ and ‘await’
- Understanding async / await in C#
await Task.CompletedTask for what?
It is there to make it easier for later stage to implement async code calls without having to alter the signature thus preventing having to refactor the calling code.
Whilst the scaffolded sample code is synchronous, the Template Studio is designed specifically around an async data access layer, you are expected to implement your own data access by modifying the body of the generated methods.
If the async implementation were NOT implemented, there would be significant code changes throughout the templated app and it would be a very steep learning curve for new developers, the point of the template is to get up and running with minimal effort or even experience!
Another option would be to remove the async
keyword from the method signature and that line and do
return Task.FromResult<IEnumerable<SampleModel>>(data);
You see this construct when you need to return an awaitable Task due to an interface for example while the implementation has no async work to do.
In this case however, since it is a template they expect people to replace the await Task.Completed
with something like await FetchDataFromDatabaseAsync();
. Since the async
keyword is already there it minimizes the needed changes to implement your own async call.
Anyway, without this await construct you can do this:
public class SampleModelService
{
public Task<IEnumerable<SampleModel>> GetDataAsync()
{
var data = new List<SampleModel>();
data.Add(new SampleModel
{
Title = "Lorem ipsum dolor sit 1",
Description = "Lorem ipsum dolor sit amet",
Symbol = Symbol.Globe
});
data.Add(new SampleModel
{
Title = "Lorem ipsum dolor sit 2",
Description = "Lorem ipsum dolor sit amet",
Symbol = Symbol.MusicInfo
});
return Task.FromResult<IEnumerable<SampleModel>>(data);
}
}
If there is no requirement to return a Task at all (you do not have any async code) then just remove it completely. (But then you have to refactor code that calls this method)
Reviewing this code I suspect someone is going to call an async method later in the development process and already anticipated that by specifying that this method returns a Task
.
Does await Task.CompletedTask mean the async method will run synchronously?
Yes, this code will always run synchronously; the main continuation compiler goo is only invoked when the first incomplete awaitable is encountered.
You can see this in sharplab - in particular, here:
awaiter = Task.CompletedTask.GetAwaiter();
if (!awaiter.IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = awaiter;
<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
return;
}
It is the AwaitUnsafeOnCompleted(...)
+ return
that implements asynchronicity.
What is an alternative for Task.FromResultT() for tasks that represent operations returning void
Task<T>
extends Task
- so it's reasonably common to just use Task.FromResult<object>
and provide an empty result. For example:
Task ret = Task.FromResult<object>(null);
(Or use a value type - it really doesn't matter much.)
Of course, as tasks are immutable you could create a singleton instance of this and return it every time you want to return a completed task. (I believe that's what the async/await infrastructure does, in fact - or at least did in beta releases...)
As Asad noted, you can use Task.CompletedTask
, but only if you're targeting .NET 4.6. (Actually, it's not clear whether it's supporting in .NET 4.5 or not - the documentation shows ".NET Framework 4.6 and 4.5" as the version number, but then says "Supported in: 4.6"...)
Related Topics
How to Transfer Authentication from Webbrowser to Webrequest
Using the C# Dispatcher in Wpf Applications
How to Get Urls of Open Pages from Chrome and Firefox
How to Enumerate Through a Jobject
What Is the Use of the Arraysegment<T> Class
Restore a Minimized Window of Another Application
How to Add Xmlinclude Attribute Dynamically
Overriding Savechanges and Setting Modifieddate, But How to Set Modifiedby
How to Do .Net Binary Serialization of an Object When You Don't Have the Source Code of the Class
Running Msbuild Programmatically
How to Use Webbrowser Control Documentcompleted Event in C#
How to Round Up Value C# to the Nearest Integer
Asp .Net MVC Disable Client Side Validation at Per-Field Level