How to declare and await an async delegate?
Asked Answered
R

1

6

For some reason, despite this question coming up a lot in my googling, I can't seem to find an actual answer. Maybe I'm just using delegates wrong, I'm not sure. I'm happy for alternative ways of handling this if it's an X-Y problem.

Say I have this:

public class SomeLibrary
{
    public delegate void OnSomethingHappened(EventInfo eventInfo);
    public OnSomethingHappened onSomethingHappened;
    
    public void SomeMethod()
    {
        // ...
        
        // Something happened here, so we'd better trigger the event
        onSomethingHappened?.Invoke(eventInfo);
        
        // ...
    }
}

public class MyCode
{
    public void SomeInitialisationMethod()
    {
        SomeLibrary someLibrary = new SomeLibrary();
        someLibrary.onSomethingHappened += SomeEventHandler;
    }
    
    private void SomeEventHandler(EventInfo eventInfo)
    {
        DoSyncProcessing(eventInfo);
    }
}

That should all be fine (barring silly typos).

Now imagine my regular synchronous DoSyncProcessing function suddenly has to become asyncronous, like in this magic non-functional code:

public class SomeLibrary
{
    public async delegate Task OnSomethingHappened(EventInfo eventInfo); // <<< IDK what I'm doing here!
    public OnSomethingHappened onSomethingHappened;
    
    public void SomeMethod()
    {
        // ...
        
        // Something happened here, so we'd better trigger the event
        await onSomethingHappened?.Invoke(eventInfo);                            // <<< IDK what I'm doing here either!
        
        // ...
    }
}

public class MyCode
{
    public void SomeInitialisationMethod()
    {
        SomeLibrary someLibrary = new SomeLibrary();
        someLibrary.onSomethingHappened += SomeEventHandler;
    }
    
    private async Task SomeEventHandler(EventInfo eventInfo)
    {
        await DoAsyncProcessing(eventInfo);
    }
}

How can I handle that? What's the correct way to do this?

Ras answered 10/9, 2021 at 7:22 Comment(2)
The compiler gives you a very strong hint here: CS0106 "The modifier 'async' is not valid for this item" - so... just remove the async modifier?Alina
@MarcGravell Turns out you're right, I just somehow screwed up my testing of that. I mean I knew async wasn't valid in that context but it seemed like I couldn't await the delegate invocation for whatever reason. Nevermind, it does work after all.Ras
H
13

The async modifier affects the method implementation, not the signature. So change this:

public async delegate Task OnSomethingHappened(EventInfo eventInfo);

To this:

public delegate Task OnSomethingHappened(EventInfo eventInfo);

and your code will work.

Hudibrastic answered 10/9, 2021 at 7:25 Comment(3)
And then await onSomethingHappened?.Invoke(); is valid? The compiled complained when I tried this. If it should be valid then maybe I did something wrong?Ras
@Ras You can await any method that returns a Task (or other awaitable).Hudibrastic
Wow you're right. Somehow I must have screwed up my testing. I knew that it should work if the delegate returned a Task but when it didn't work I assumed it must be more complex than I thought. Sigh. I guess this is what happens when you spend two full days refactoring a giant mess :|Ras

© 2022 - 2024 — McMap. All rights reserved.