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.
Related
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.
My Xamarin.Forms app has several interfaces (for Dependencys) with implementations for Android and iOS. The methods in them are not async. Now I want to add the implementations for these interfaces for UWP, but several of the needed methods are async so they don't fit the signatures. How do I deal with this? Is the only solution to create a separate interface for UWP?
In these scenarios I tend to use the Task.FromResult method for the non-async implementations. Example: you have a method on Windows that returns a Task of type bool and you want to implement the same functionality on Android and iOS for methods that return bool.
public interface ISample
{
public Task<bool> GetABool();
}
On Windows you would just return the Task
public class WindowsSample : ISample
{
public Task<bool> GetABool()
{
// whatever implementation
return SomeTaskOfTypeBool();
}
}
On Android or iOS you would wrap the value in a Task
public class AndroidSample : ISample
{
public Task<bool> GetABool()
{
// replace with however you get the value.
var ret = true;
return Task.FromResult(ret);
}
}
You can not use the await keyword. You have to create a new Task and wait for the Task to finish. A separate interface is not necessary. Exception handling with Tasks can be tricky, inform yourself.
Calling an async method Method1 with return value:
string s = Task.Run(() => Method1()).Result;
Without return value:
Task.Run(() => Method1()).Wait;
.Rest or .Wait block until the Task is completed.
More Details:
Calling async methods from non-async code
I have the interface:
public interface IService
{
Task<double> GetData(int id);
}
And I need to use this interface in my class:
//_svc is a Type of IService
public async void Doit()
{
Task<double> task = await _svc.GetData(id);
}
And when I do it, it says that it can't convert type double into Task<double>
Why is this double instead of the task? The interface clearly specifies that this is a task and here I need to get the task, not the value.
If you need the task to handle it yourself, then remove the await that handles it for you.
It is not an answer, but i hope it will help you to understand Tasks a little bit more. For example you have interface with method:
System.Threading.Tasks.Task<string> FindNameAsync(string computerName);
When you call a method from interface, it will be something like this:
var result = await _scv.FindNameAsync(name); //The program will not go to next line, until it becomes result
When it will get result it will go further. And result you can pass to next methods
EDIT
If you want to get statuses you can make little modifications:
System.Threading.Tasks.Task<bool> FindNameAsync(string computerName);
Then you can return true in case of success, in other case - false.
With a little modification you can pass object to method as parameter and save values that you need in it. Or you can return dictionary or turple, and not bool. Little example:
Your method can be like here:
System.Threading.Tasks.Task<bool> FindNameAsync(SomeClass obj);
And you can handle it so:
SomeClass test = new SomeClass();
if(await _scv.FindNameAsync(test))
{
//code for success result
}else
{
//if error happened handle here
}
The interface clearly specifies that this is a task and here I need to get the task, not the value.
When an interface declares a method that returns a Task or Task<T> the name of the method should - by convention - also end with "Async": https://msdn.microsoft.com/en-us/library/hh191443
Such a method is expected to be implemented as an async method that returns an object of type T if the return type is declared as Task<T> or nothing at all if the return type is just Task:
public interface IService
{
Task<double> GetDataAsync(int id);
}
public class Service : IService
{
public async Task<double> GetDataAsync(int id)
{
await Task.Delay(1000);
return 1.0;
}
}
You would await such a method:
public class Consumer
{
public async void Doit()
{
IService service = new Service();
double d = await service.GetDataAsync(1);
}
}
Now whether the method actually is implemented as an async method is an implementation detail in the concrete implementation of the interface but it doesn't really matter as far as the consumer of the interface is concerned as you can still always await a method that returns Task or Task (provided that the caller method is marked with the async keyword of course).
You would for example be able to await the following non-async implementation of the method the same way:
public class Service : IService
{
public Task<double> GetDataAsync(int id)
{
return Task.FromResult(1.0);
}
}
So methods that have a return type of Task or Task<T> are meant to be asynchronous and awaited.
You could still store an instance of the method's actual return type in a variable "as usual" though:
public void Doit()
{
IService service = new Service();
Task<double> task = service.GetDataAsync(1);
}
This would however simply call the asynchronous without waiting for its return value which makes it pretty useless to even call the method in the first place. When calling a - by contract and convention asynchronous - method that returns a Task<double> you are interested in getting the double value back asynchronously. You don't really care about the Task object itself if you understand what I mean.
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.
In contrast to Task.Wait() or Task.Result, await’ing a Task in C# 5 prevents the thread which executes the wait from lying fallow. Instead, the method using the await keyword needs to be async so that the call of await just makes the method to return a new task which represents the execution of the async method.
But when the await’ed Task completes before the async method has received CPU time again, the await recognizes the Task as finished and thus the async method will return the Task object only at a later time. In some cases this would be later than acceptable because it probably is a common mistake that a developer assumes the await’ing always defers the subsequent statements in his async method.
The mistaken async method’s structure could look like the following:
async Task doSthAsync()
{
var a = await getSthAsync();
// perform a long operation
}
Then sometimes doSthAsync() will return the Task only after a long time.
I know it should rather be written like this:
async Task doSthAsync()
{
var a = await getSthAsync();
await Task.Run(() =>
{
// perform a long operation
};
}
... or that:
async Task doSthAsync()
{
var a = await getSthAsync();
await Task.Yield();
// perform a long operation
}
But I do not find the last two patterns pretty and want to prevent the mistake to occur. I am developing a framework which provides getSthAsync and the first structure shall be common. So getSthAsync should return an Awaitable which always yields like the YieldAwaitable returned by Task.Yield() does.
Unfortunately most features provided by the Task Parallel Library like Task.WhenAll(IEnumerable<Task> tasks) only operate on Tasks so the result of getSthAsync should be a Task.
So is it possible to return a Task which always yields?
First of all, the consumer of an async method shouldn't assume it will "yield" as that's nothing to do with it being async. If the consumer needs to make sure there's an offload to another thread they should use Task.Run to enforce that.
Second of all, I don't see how using Task.Run, or Task.Yield is problematic as it's used inside an async method which returns a Task and not a YieldAwaitable.
If you want to create a Task that behaves like YieldAwaitable you can just use Task.Yield inside an async method:
async Task Yield()
{
await Task.Yield();
}
Edit:
As was mentioned in the comments, this has a race condition where it may not always yield. This race condition is inherent with how Task and TaskAwaiter are implemented. To avoid that you can create your own Task and TaskAwaiter:
public class YieldTask : Task
{
public YieldTask() : base(() => {})
{
Start(TaskScheduler.Default);
}
public new TaskAwaiterWrapper GetAwaiter() => new TaskAwaiterWrapper(base.GetAwaiter());
}
public struct TaskAwaiterWrapper : INotifyCompletion
{
private TaskAwaiter _taskAwaiter;
public TaskAwaiterWrapper(TaskAwaiter taskAwaiter)
{
_taskAwaiter = taskAwaiter;
}
public bool IsCompleted => false;
public void OnCompleted(Action continuation) => _taskAwaiter.OnCompleted(continuation);
public void GetResult() => _taskAwaiter.GetResult();
}
This will create a task that always yields because IsCompleted always returns false. It can be used like this:
public static readonly YieldTask YieldTask = new YieldTask();
private static async Task MainAsync()
{
await YieldTask;
// something
}
Note: I highly discourage anyone from actually doing this kind of thing.
Here is a polished version of i3arnon's YieldTask:
public class YieldTask : Task
{
public YieldTask() : base(() => { },
TaskCreationOptions.RunContinuationsAsynchronously)
=> RunSynchronously();
public new YieldAwaitable.YieldAwaiter GetAwaiter()
=> default;
public new YieldAwaitable ConfigureAwait(bool continueOnCapturedContext)
{
if (!continueOnCapturedContext) throw new NotSupportedException();
return default;
}
}
The YieldTask is immediately completed upon creation, but its awaiter says otherwise. The GetAwaiter().IsCompleted always returns false. This mischief makes the await operator to trigger the desirable asynchronous switch, every time it awaits this task. Actually creating multiple YieldTask instances is redundant. A singleton would work just as well.
There is a problem with this approach though. The underlying methods of the Task class are not virtual, and hiding them with the new modifier means that polymorphism doesn't work. If you store a YieldTask instance to a Task variable, you'll get the default task behavior. This is a considerable drawback for my use case, but I can't see any solution around it.