How to await for override async function? - c#

We have a generic Job class which have an abstract HeavyTask method like this:
abstract class Job {
private Task m_task;
protected abstract void HeavyTask();
public void StartJob(){
m_task = Task.Run(() => HeavyTask());
}
public async Task WaitJob(){
await m_task;
}
}
And the derived class override the HeavyTask function and also make it async:
class JobFoo : Job {
protected override async void HeavyTask()
{
await Task.Delay(1000);
Debug.WriteLine("JobFoo is done");
}
}
Then when we are using this method, it seems that the HeavyTask() is not awaited:
Job job = new JobFoo();
job.StartJob();
await job.WaitJob();
Debug.WriteLine("All Done");
Output:
All Done
JobFoo is Done
If we don't have async for the override HeavyTask, then it is working as expected. But I cannot guarantee those whose override the Job won't make the HeavyTask async. I want to understand why it is not awaited successfully and is there a way to make sure it will awaited? If you can, could you also explain whether it is a good practice to override a non-async function as async as shown above?

It's not awaited because there's no awaitable (i.e. Task) to await. That method has a void return type. And you should avoid using async void outside of event handlers.
If you want to enable a derived class to use async have the method return a Task to begin with:
protected abstract Task HeavyTaskAsync();
And if you then need to have a synchronous override return a Task synchronously:
override Task HeavyTaskAsync()
{
// do stuff;
return Task.CompletedTask;
}

I don't think this line is awaitable:
m_task = Task.Run(() => HeavyTask());
What is it spouse to wait for? No value is returned.
how about
Task.Run(() => HeavyTask()).Wait();

Related

How to create and implement interfaces for operations that are only sometimes async

Let's say I have 100s of classes that implement a common interface with a method "calculate". Some of the classes will execute async (e.g. read a file), and other classes implementing the same interface will execute code that is sync (e.g. adding two numbers). What is a good way to code this, for maintenance and for performance?
The posts I read so far, always recommend to make async/await methods bubble up to the callers. So if you have one operation that is async, make the caller async, then its caller async, and so on. So this makes me think that the interface should be an async interface. However, this creates a problem when implementing the interface with code that is synchronous.
One idea I thought of is to expose in the interface 2 methods, one async and one sync, and one boolean property to tell the caller which method to call. This would look really ugly though.
The code I currently have is only one interface method that is async. Then for implementations that are synchronous, they wrap the code inside a Task object:
using System.IO;
using System.Threading.Tasks;
namespace TestApp
{
interface IBlackBox
{
Task<string> PullText();
}
sealed class MyAsyncBlackBox : IBlackBox
{
public async Task<string> PullText()
{
using (var reader = File.OpenText("Words.txt"))
{
return await reader.ReadToEndAsync();
}
}
}
sealed class MyCachedBlackBox : IBlackBox
{
public Task<string> PullText()
{
return Task.Run(() => "hello world");
}
}
}
Is this the right approach to create and implement an interface that is only sometimes async? I have a lot of classes that implement short synchronous operations, and worry that this could add a lot of overhead. Is there some other way to do this that I am missing?
This is a common situation with interfaces. If you have a contract that needs to specify a task for the Async Await Pattern and we have to implement that Task in the interface.
Assuming the caller is going to use await you can just drop the async and return a Task.
However, you need to be-careful with your exceptions. It's assumed that exceptions are placed on the task. So to keep this plumbing the caller will expect you have to handle them slightly differently.
Common usages
Standard async
public async Task<string> PullText()
{
using (var reader = File.OpenText("Words.txt"))
{
return await reader.ReadToEndAsync();
}
}
Returning a Task for CPU bound work (capturing the exception and placing it on the Task)
public Task<string> PullText()
{
try
{
return Task.Run(() => DoCpuWork());
}
catch (Exception e)
{
return Task.FromException<string>(e);
}
}
Slightly less efficient as we are plumbing an IAsyncStateMachine
public async Task<string> PullText()
{
return await Task.Run(() => DoCpuWork());
}
Returning a completed Task with a simple results (capturing the exception and placing it on the Task)
public Task<string> PullText()
{
try
{
// simplified example
return Task.FromResult("someString");
}
catch (Exception e)
{
return Task.FromException<string>(e);
}
}
There is also a 3rd approach, you can use the async keyword, and pragma out the warnings, this takes care of the error semantics for you. This feels a little dirty to me, just because it looks messy and the need to pragma out the warning, though I have now seen this used in bespoke production libraries
#pragma warning disable 1998
public async Task<string> PullText()()
#pragma warning restore 1998
{
return Task.Run(() => "hello world");
}
and
#pragma warning disable 1998
public async Task<string> PullText()()
#pragma warning restore 1998
{
return Task.FromResult("someString");
}
Note all the above deal with returning a Task<T> from the method. If one was just wanting to return the Task you can take advantage of Task.CompletedTask; with the same error semantics as above.
Usually in these cases, You have something in front of the call that is handling the request and passing it off to the "worker" classes (e.g. TestApp). If this is the case, I don't see why having an "IAsyncable" interface where you could test if the class was async capable would not work.
if(thisObject is IAscyncAble) {
... call the ansync request.
}
I ended up using the following code:
using System.IO;
using System.Threading.Tasks;
namespace TestApp
{
interface IBlackBox // interface for both sync and async execution
{
Task<string> PullText();
}
sealed class MyAsyncBlackBox : IBlackBox
{
public async Task<string> PullText()
{
using (var reader = File.OpenText("Words.txt"))
{
return await reader.ReadToEndAsync();
}
}
}
sealed class MyCachedBlackBox : IBlackBox
{
public Task<string> PullText() // notice no 'async' keyword
{
return Task.FromResult("hello world");
}
}
}

How do you implement chainable async extension methods?

I am wondering how to write chainable, async extension methods without requiring the caller to write multiple awaits and nested parentheses.
Example. Let's say your goal is for the caller to be able to write this sort of snippet:
var example = new MyCompilableClass();
await example.Compile().Run();
(Note: I'm not writing a compiler. I am just using these names to make it clear that one has to happen before the other).
To support the above, you create two interfaces:
public interface ICompilable
{
Task<IRunnable> CreateExecutableImage();
}
public interface IRunnable
{
Task Execute();
}
You implement them as async:
class SourceCode : ICompilable
{
public async Task<IRunnable> CreateExecutableImage()
{
await Stub.DoSomethingAsynchronous();
return new ObjectCode();
}
}
class ObjectCode : IRunnable
{
public async Task Execute()
{
await Stub.DoSomethingAsynchronous();
}
}
And then write the two extension methods with appropriate type constraints:
static class ExtensionMethods
{
public static async Task<IRunnable> Compile<T>(this T This) where T : ICompilable
{
return await This.CreateExecutableImage();
}
public static async Task Run<T>(this T This) where T : IRunnable
{
await This.Execute();
}
}
So now the caller tries to compile his code. But we get an error on this line:
await example.Compile().Run(); //Does not compile
Here is the compilation error:
The type 'System.Threading.Tasks.Task' cannot be used as type parameter 'T' in the generic type or method 'ExtensionMethods.Run(T)'. There is no implicit reference conversion from 'System.Threading.Tasks.Task' to 'Example.IRunnable'
We can fix the compilation error with parentheses:
(await example.Compile()).Run();
...or two lines of code:
var compiled = await example.Compile();
await compiled.Run();
...which both work. But that seems rather unfortunate if you were looking forward to a clean, chainable syntax as we have with LINQ.
Is there a different way to implement these extension methods, so that they keep their asynchronous nature, but without requiring the ugly syntax?
Here is a Link to DotNetFiddle if you'd like to work with my example code.
One simple answer is just to add another extension method that converts the Task<T> to a T, like this:
static class ExtensionMethods
{
public static async Task Run<T>(this T This) where T : IRunnable
{
await This.Execute();
}
public static async Task Run<T>(this Task<T> This) where T : IRunnable
{
////Await the task and pass it through to the original method
await (await This).Execute();
}
}
This will enable the caller to use
await example.Compile().Run();
...although he may have no idea he is passing the task, not the result, to Run() (unless he really thinks about it). Shouldn't matter to him.

Async method doesn't get executed even when it gets called

My workflow: Constructor -> Calls async Method 1 -> Calls async Method 2 -> Calls async Method 3
Constructor:
public MyConstructor() {
Method1();
}
Method1:
private async void Method1() {
//do some stuff
await Method2();
//do some more stuff
}
Method 2:
protected internal async Task Method2() {
//do some stuff
var x = await Method3("someParams");
//do some more stuff
}
Method 3:
public async Task<List<string>> Method3(string someParams) {
Debug.WriteLine("I am here"); //Breakpoint doesn't get hit, no output "I am here"
}
Yeah I know, you probably wonder why I am using so many different async methods.. But there is some more stuff going on (but nothing that influences the problem!). The problem is, Debug.WriteLine("I am here"); does not get hit, and no exception is thrown.
What am I doing wrong?
In a nutshell: yes, as #fknx mentioned in a comment, the problem is that the code executes asynchronously and is not awaited, therefore the app exits before reaching the line in question.
There are a couple of bad practices in your example:
async void method
It is not a good idea to create such things as you loose track of the task. Please always define Task as the return value, it does not cost anything and it will help you write a correct API.
asynchronous call in a constructor
This is not a good design either, because (as you mentioned) you cannot await this method in a constructor so you will just fire up the task and loose it. Please consider using an async Init method instead.
So instead of this:
public class MyCustomClass
{
public MyCustomClass()
{
// BAD CODE, do not do this
Method1();
}
private async Task Method1()
{
//do some stuff
await Method2();
//do some more stuff
}
}
You could do this:
class Program
{
static void Main(string[] args)
{
var m = new MyCustomClass();
m.InitializeAsync().Wait();
Console.WriteLine("Before exit...");
}
}
public class MyCustomClass
{
public MyCustomClass()
{
// in a constructor you should not do anything async
}
public async Task InitializeAsync()
{
await Method1();
}
private async Task Method1()
{
//do some stuff
await Method2();
//do some more stuff
}
}
It is absolutely OK to Wait for an async method in the Main method, or to be precise your console app should have only one Wait (or WaitAll, or whatever) method in the main method (and nowhere else) if you want to create a truly async app.

Async programmic and virtual functions

If I have an interface such as:
using System.Threading.Tasks;
...
public interface IFoo
{
Task doIt();
Task<bool> doItAndReturnStuff();
}
and one of the classes implementing this interface just happens to not require async methods, how can i correct override these functions?
In other words, how do I correctly return "void" and "bool" wrapped in Task objects?
For example:
public class FooHappensToNotNeedAsync : IFoo
{
public override Task doIt()
{
// If I don't return anything here, I get
// error that not all code paths return a value.
// Can I just return null?
}
public override Task<bool> doItAndReturnStuff()
{
// If I want to return true, how to I do it?
// This doesn't work:
return true;
}
}
NOTE - I can't strip the Task stuff completely because some of the classes that implement this interface are in fact asynch.
Thanks
It's not clear what you're trying to achieve, but one approach (which would look the most like "normal" code) is probably just to make them async methods anyway:
public async Task DoIt()
{
// No-op
}
public async Task<bool> DoItAndReturnStuff()
{
return true;
}
Without any await expressions, the method will complete synchronously anyway. You'll get a warning on each method, but you could disable that just for this piece of code using a #pragma.
Alternatively - and I guess more simply in terms of not requiring a #pragma to disable warnings - would be to use Task.FromResult:
public Task DoIt()
{
// Returns a Task<bool>, but that's okay - it's still a Task
return Task.FromResult(true);
}
public Task<bool> DoItAndReturnStuff()
{
return Task.FromResult(true);
}

Unable to declare Interface " async Task<myObject> MyMethod(Object myObj); " [duplicate]

This question already has answers here:
Error: "Cannot use 'async' on methods without bodies". How to force async child overrides?
(2 answers)
Closed 1 year ago.
I'm unable to declare
interface IMyInterface
{
async Task<myObject> MyMethod(Object myObj);
}
The compiler tells me:
The modifier async isn't valid for this item
The async modifier can only be used for methods that have a body
Is this something that should be implemented, or does the nature of async & await prohibit this from ever occurring?
Whether a method is implemented using async/await or not is an
implementation detail. How the method should behave is a contract
detail, which should be specified in the normal way.
Note that if you make the method return a Task or a Task<T>, it's more
obvious that it's meant to be asynchronous, and will probably be hard
to implement without being asynchronous.
From https://stackoverflow.com/a/6274601/4384
Whether or not your implementation is async, has no relevance to your interface. In other words, the interface cannot specify that a given method must be implemented in an asynchronous way.
Just take async out of your interface and it will compile; however, there is no way to enforce asynchronous implementation just by specifying an interface.
If you have an interface with two implementations (one that is truly async and the other that is synchronous) this is what it would look like for each implementation - with both returning a Task<bool>.
public interface IUserManager
{
Task<bool> IsUserInRole(string roleName);
}
public class UserManager1 : IUserManager
{
public async Task<bool> IsUserInRole(string roleName)
{
return await _userManager.IsInRoleAsync(_profile.Id, roleName);
}
}
public class UserManager2 : IUserManager
{
public Task<bool> IsUserInRole(string roleName)
{
return Task.FromResult(Roles.IsUserInRole(roleName));
}
}
If it is a void method you need to return Task.CompletedTask; from the non async method
(I think .NET 4.5 and later)
See also : Return Task<bool> instantly
The async modifier is an 'implementation detail', it affects how a method can do stuff asynchronously, not if it does so.
So async has no business being inside an interface.
interface IService { Task DoSomethingAsync(); }
class A : IService { public async Task DoSomethingAsync() { ... } }
class B : IService { public Task DoSomethingAsync() { ... } }
Classes A and B are both perfectly valid. Both methods are awaitable. A consumer of the interface doesn't know or care if they use async.
B.DoSomethingAsync() can be and probably will be asynchronous.

Categories

Resources