Mick Mick - 3 months ago 14
C# Question

Is async partial void MyPartialMethod() dangerous?

I've seen a lot of warnings about writing code such as...

public async void MyDangerousMethodWhichCouldCrashMyApp...


I've read that its OK with Eventhandlers as they must return void. However partial methods must also return void. You can have the following code...

static void Main(string[] args)
{
MainAsync().Wait();
Console.ReadLine();
}

async static Task MainAsync()
{
MyCodeGeneratedClass c = new MyCodeGeneratedClass();
try
{
await c.MyCodeGeneratedMethod();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}

public partial class MyCodeGeneratedClass
{
public async Task MyCodeGeneratedMethod()
{
HttpClient client = new HttpClient();
Console.WriteLine(await client.GetStringAsync("http://msdn.microsoft.com"));
MyCustomCode();
}

partial void MyCustomCode();
}


and then implement as...

partial class MyCodeGeneratedClass
{
async partial void MyCustomCode()
{
HttpClient client = new HttpClient();
Console.WriteLine(await client.GetStringAsync("http://msdn.microsoft.com"));
throw new Exception("Boom");
}
}


But what will happen to the application if the implementation of MyCustomCode encounters an exception?

If it's a no go, given how prevalent async / await is, does that mean partial methods are essentially obsolete? Should code generation systems stop exposing partial methods in favour of events or perhaps better still empty protected virtual methods in a base class? i.e.

protected virtual Task MyCustomCode(T foo)
{
return Task.FromResult(0);
}


EDIT: OK so I've made several updates to the code. After the original pseudo code I wrote didn't get well received. The code above I think demonstrates that there's definitely an issue with async partial void MyPartialMethod as the call to MyCodeGeneratedMethod does seem to bring down the app domain, despite the try catch around the call. I'm just wondering if there are better options than moving to protected virtual base class methods.

Answer

But what will happen to the application if the implementation of MyCustomCode encounters an exception?

The semantics for async void methods are that exceptions are raised directly on the SynchronizationContext that was current at the beginning of the method. This and other fun facts about async void are covered in my async best practices article.

does that mean partial methods are essentially obsolete?

Equally as obsolete as event handlers. So, no, not really. However, they weren't updated to allow a return type of Task, so it seems like they're a language feature that isn't being actively updated with the rest of the language.

Should code generation systems stop exposing partial methods in favour of events or perhaps better still empty protected virtual methods in a base class?

Events wouldn't change this at all; they'd still be implemented with async void.

If a "hook" needs to be asynchronous, then that changes all the generated code, since it must also all be asynchronous.

An async partial method would only not work if the generated code needed some result from that partial method and the implementation had to do some asynchronous work in order to generate that result. In my experience, partial methods are conceptually more like events, so async void would be acceptable.