0

I'd like to know if the following use of async-await is safe given the apparent mix of asynchronous and synchronous code.

You have a derived class which overrides a virtual method and adds the async keyword to the method signature to declare it will do something asynchronous.

Note how in this exemple Foo calls Bar, and Bar in this case is derived and asynchronous, yet Foo does not await the call. It couldn't if it wanted to, on the base class the signature for Bar is synchronous.

public class BaseClass
{
    public virtual void Foo()
    {
        Bar(); // note: there is no await on this call, yet Bar is async in derived class
    }

    protected virtual void Bar()
    {
        Console.WriteLine("Base.Bar");
    }
}

// Derived class has implementation for Bar() which is asynchronous
// is that a problem? The compiler builds this, should we be worried about async and sync being mixed?
//
public class DerivedClass : BaseClass
{
    protected override async void Bar()
    {
        Console.WriteLine("Derived.Bar");
        await Task.Delay(1000);
    }
}

class Program
{
    static void Main(string[] args)
    {
        var derived = new DerivedClass();
        derived.Foo(); // note: there is no await on this call, yet Foo becomes async when it calls Bar which is async.
    }
}

The reason I'm asking is that in Xamarin on Android it's recommended to override OnStart and add the async keyword when you want to do asynchronous code when an activity starts. Yet the method on the base Activity class is not async.

mipnw
  • 2,135
  • 2
  • 20
  • 46
  • 2
    The main issue is that it is `async void` instead of `async Task`. That is not what you want, usually. You can't await it and its exceptions get handled differently. See [what is the difference between async void and async Task?](https://stackoverflow.com/questions/8043296/whats-the-difference-between-returning-void-and-returning-a-task). – John Wu Apr 17 '18 at 23:50
  • 1) Yes, you can add `async` to the `OnStart` **void** override method, the keyword flags a compiler transform to implement the code as a state machine. 2) `Xamarin on Android it's recommended to override OnStart and add async` Where is that recommendation coming from(?) because it really depends upon what you are doing before & after that awaited task in the `OnStart` that can be a problem, consult the Activity lifecycle to understand the method flow. – SushiHangover Apr 17 '18 at 23:58
  • Actually the language supports async void, whether or not it's a good idea depends on the situation, an event handler is async void. The question isn't about the return type nor exception handling – mipnw Apr 18 '18 at 00:06
  • It is just one of ways how it is obvious that async was a bolt-on and never considered when C# was originally designed. You cannot declare a virtual base method *async* and ensure that a derived one is as well. Same story for an event. You don't have a choice here. It is typically very troublesome, but not much to fear from OnStart() since you'd expect your app to stay around for a while and not die horribly when it terminates but the async code isn't done yet. – Hans Passant Apr 18 '18 at 00:10
  • Just an FYI: `Activity.OnStart` is not an event handler in the context of an Android Activity (and thus `Xamarin.Android`). It is part of a lifecycle method chain and an Android-based API, so unless Xamarin decides to auto-generates `async` into all the generated C#/JNI/Java wrapper code (a bad choice of course), you can & need to apply `async` to the overridden void based Android Activity lifecycle methods to `await` a Task within them (unless creating a Task and calling Start on it in a fire/forget pattern is appropriate for the code you need to execute). – SushiHangover Apr 18 '18 at 00:25

0 Answers0