I am looking at the code for DbDataReader (also DbCommand) at MS reference and can't figure out what is async in ReadAsync() method.
virtual public Task<bool> ReadAsync(CancellationToken cancellationToken) {
if (cancellationToken.IsCancellationRequested) {
return ADP.CreatedTaskWithCancellation<bool>();
}
else {
try {
return Read() ? ADP.TrueTask : ADP.FalseTask;
}
catch (Exception e) {
return ADP.CreatedTaskWithException<bool>(e);
}
}
}
The ReadAsync method just calls Read method and returns a complete task.
Doesn't this block the calling thread the same way as calling Read directly?
I have noticed the same pattern in DbCommand ExecuteReaderAsync and other methods. They just call the sync versions and return completed Tasks.
What am I missing here?
UPDATE: I did not miss anything, as #PeterBons explained nicely (also in the documentation). I still don't like it, but that's my problem.
You are looking at a virtual method in an abstract class. If you want (future) implementations to be able to do some truly async work you will have to define a method signature that allows that. So it should return a Task or Task<T>. Remember that just using a Task does not make anything asynchronous, it makes it awaitable.
The use of the Task<bool> return type in this example virtual method is to facilitate other classes that derive from DbDataReader to provide real async behavior in their implementation of ReadAsync.
For example, a truly async implementation could do something like
class TrueAsyncReader : DbDataReader
{
...
public override async Task<bool> ReadAsync(CancellationToken cancellationToken)
{
...
return await ReadFromDbAsync();
}
}
As you can see you can now have async and non async implementations, without having to alter the method signature.
Since you can easily call synchronous code from an async method this is the way to go. Calling async code from a synchronous method is a nog go.
for non async implementations that need to return a task you can return something like Task.FromResult<T> or Task.CompletedTask. This will not block.
See also await Task.CompletedTask for what?
To summarize: the default implementation does not do anything async but derived classes can without having to change the method signature.
Related
This question already has answers here:
How to implement interface method that returns Task<T>?
(4 answers)
Closed 6 years ago.
I am working with a third-party dll which exposes methods which return Task and Task<T>. I don't have any control over this assembly or the interface, and I assume the author assumed everything would need to be async since the naming of the methods are *Async() as shown below.
Given that, how do I properly implement the interface if I don't actually have any asynchronous code running?
public interface IFoo
{
Task DoWorkAsync();
Task<int> GetValueAsync();
}
My attempt was the following:
public class FooBar : IFoo
{
public async Task DoWorkAsync()
{
// Do Some Work
await Task.Yield();
}
public async Task<int> GetValueAsync()
{
// Do Some Work
var result = ...;
return Task.FromResult(result);
}
}
Additionally:
Was the author correct in exposing only methods that returned Task/Task<T>?
Was the author correct in suffixing method names with *Async()? Code analysis doesn't complain if I write an async method without appending Async to the name.
If you don't have async work to do don't include the async keyword. Your GetValueAsnyc function was almost correct, you just needed to drop the async. For your DoWorkAsync you should just not mark the method async and return a completed task.
public class FooBar : IFoo
{
public Task DoWorkAsync()
{
// Do Some Work
//If you can use .NET 4.6
return Task.CompletedTask;
//For older versions, the thing you pass in does not matter, I like to use bool.
return Task.FromResult(false);
}
public Task<int> GetValueAsync()
{
// Do Some Work
var result = ...;
return Task.FromResult(result);
}
}
However, if your code is slow and you end up blocking the UI for a long period of time I would consider looking in to if you can re-write your code as actually being async or perhaps wrapping the code in to a background thread, but I would only do a background thread if it was a last resort.
I have a virtual method that sometimes contain await calls and sometimes doesn't. The IDE does give me warning, what is the proper way of handling this ?
In my base class:
protected virtual async Task GoNext ()
From the base class it get called via await.
Then in my sub-classes i override this method but there are times that it does include a await and times that it doesn't.
The async keyword is not actually part of the inherited method signature, but more of a signal to the compiler that it needs to compile and rewrite the method according to the pattern for async methods.
As such, you can leave out the async keyword on inherited methods if the inherited method does not use the await keyword.
Note that you will still have to return a Task or Task<T>, that part is part of the inherited method signature.
So this will give you a warning:
class Base
{
public virtual async Task<int> Method()
{
await Task.Delay(10);
return 42;
}
}
class Derived : Base
{
// next line produces warning
public override async Task<int> Method()
{
return 42;
}
}
The warning is this:
Warning: CS1998 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.
This, however, will not produce a warning:
class Derived : Base
{
public override Task<int> Method()
{
return Task.FromResult(42);
}
}
Note that I changed the return statement in that last method because part of the "magic" that the async keyword brings is to automatically wrap the return value inside a Task<T>. If you have other ways of obtaining a Task<T>, obviously you do not need to wrap the result like I did above.
I have a sync method, now I would like to implement its async version. Fortunately the underlying call already have an async version (dbSet.SaveChangesAsync()), however in my algorithm there is an if branch returning with constant literal 1.
I do not know how to implement this part in the async version?
Sync version:
public virtual int Add(T entity)
{
SetLogContext(entity, _logctx);
dbSet.Add(entity);
if (isAutonomous)
{
return ctx.SaveChanges();
}
return 1;
}
Async version:
public virtual Task<int> AddAsync(T entity)
{
SetLogContext(entity, _logctx);
dbSet.Add(entity);
if (isAutonomous)
{
return ctx.SaveChangesAsync();
}
return ??? // What to write here?
}
Use
return Task.FromResult(1);
You have two possibilities how to achieve your needs: one is to use the async keyword:
public virtual async Task<int> AddAsync<T>(T entity)
{
SetLogContext(entity, _logctx);
dbSet.Add(entity);
if (isAutonomous)
{
return await ctx.SaveChangesAsync();
}
return 1;
}
The other is to use Task.FromResult(1) at the point where you want to return the number.
The problem I see here is that you've created an "Async" method that isn't actually async. This could be pretty misleading for the next guy using it.
As #xxMUROxx already mentioned, an "Async" method should be prefixed with the async keyword.
public virtual async Task<int> AddAsync<T>(T entity)
{
SetLogContext(entity, _logctx);
dbSet.Add(entity);
if (isAutonomous)
{
return await ctx.SaveChangesAsync();
}
return 1;
}
The whole point of using the async await pattern is to change the way the program flows through methods. When the await keyword is hit, the method returns to the caller and usually flows all the way back to the original caller. Typically that'll be an async void event handler like a button click.
When this happens, it allows the calling thread to continue executing while it's waiting for a long running operation to complete. After the long running operation completes the code will create a continuation and continue executing any other code that depends on the result returned.
By omitting the async keyword from the method, you've effectively made the call synchronous again. Defeating the purpose of calling SaveChangesAsync in the first place.
Trying to understand the new async/await pattern, I have one question which I can't find an answer to, namely if I should decorate my methods with async, if I intend to call those methods from other async functions, or just return Tasks where appropriate?
In other words, which of these classes A, B or C is best, and why?
class A<T>
{
public async Task<T> foo1() //Should be consumed
{
return await foo2();
}
public async Task<T> foo2() //Could be consumed
{
return await foo3();
}
private async Task<T> foo3() //Private
{
return await Task.Run(...);
}
}
class B<T>
{
public async Task<T> foo1() //Should be consumed
{
return await foo2();
}
public async Task<T> foo2() //Could be consumed
{
return await foo3();
}
private Task<T> foo3() //Private
{
return Task.Run(...);
}
}
class C<T>
{
public async Task<T> foo1() //Should be consumed
{
return await foo2();
}
public Task<T> foo2() //Could be consumed
{
return foo3();
}
private Task<T> foo3() //Private
{
return Task.Run(...);
}
}
It seems redundant to overdecorate methods so I naturally lean toward C, but at the same time it feels somewhat awkward to work with Task<T> unless you use the await keyword.
Both versions work effectively the same, the only difference is that when you use await here, you get some performance penalty (because the state machine must be set up and a continuation will most likely be used).
So, it comes down to a tradeoff: Do you want your methods to be somewhat more efficient at the cost of being slightly less readable? Or are you willing to sacrifice performance for readability?
Usually, I would advise you to go for readability first and only focus on performance if profiling tells you it's worth it. But in this case, I think the increase in readability is small, so I would probably not use await.
Also note that your class C still doesn't go far enough: foo1() also doesn't need await.
The async in the signature is there to allow the compiler to create the state-machine rewriting of the contained code that is necessary to implement the await semantics in the general case.
Your example is exactly the special case where you do not need that rewriting: The asynchronous operation is the last thing happening within a method. That kind of method is already possible and valid in .NET4.0. This compatibility might be one reason to avoid async when you do not need it.
I found myself wanting to implement an IAwaitable class (something that implements asynchronous calls without blocking threads).
I've got the most recent version of AsyncCTP installed, and the compiler is saying that I need an IsCompleted() member. Okay, so the CTP preview has moved on a little bit (I get that, like it's a preview)
Question: What interface are the AsyncCTP language extensions expecting now?
Question: In all this I'm assuming that I can signal to the "IAwaitable" via a lamda/delegate? Is this possible? Do we call EndAwait? The intellisense suggests that you call EndAwait to retrieve the result... so that doesn't sound right. Any ideas?
All of the examples I've found so far are for features that the AsyncCTP library has already implemented such as:
await new WebClient().DownloadStringTaskAsync(uri).ConfigureAwait(false);
from the 101 AsyncSamplesCS
Background:
I find myself on Jon Skeets page (again) looking at this example
using System;
class Test
{
static async void Main()
{
await new Awaitable();
}
}
class Awaitable
{
public Awaiter GetAwaiter()
{
return new Awaiter();
}
}
class Awaiter
{
public bool BeginAwait(Action continuation)
{
return false;
}
public int EndAwait()
{
return 1;
}
}
With the SP1 refresh, you need:
Some GetAwaiter() method (possibly but not necessarily an extension method) that returns something (Awaiter in your example) with all of:
A bool IsCompleted property (get)
A void OnCompleted(Action callback)
A GetResult() method which returns void, or the desired outcome of the awaited operation
However, I suggest you look at TaskCompletionSource<T> - I looked at this, and it out-performed my naive implementation (here; obsolete). You can also use it for void tasks, by using something like a TaskCompletionSource<bool> (and exploit the fact that the Task<bool> is also an untyped Task).