4

Ok, so, I'm almost there and need just a small bit of advise to get over this hump! So, the reason i asked this questoin Async delegate - What is proper syntax? is because I'm trying to call a delegate function asynchronously (using await ...).

So, here I have a class which uses a library which accepts a delegate. The library calls the delegate when triggered. It looks something like this.

Example.Question.Base{
public static class Consumer{
    private delegate bool Redo();
    private static Redo callbackFunction;

    public static async Task<T> Go(){
        // Do some stuff ...

        // now I want to set up my delegate so this library 
        // I'm using can call back my delgate function when 
        // an event occurs that it manages
        callbackFunction = NonAsync;
        SomeLibrary someLibrary = new SomeLibary();
        await someLibrary.SomeMethod(callbackFunction);
    }

    public static bool NonAsync()
    {
        // Do some work ...
        return false;
    }
}

// so now the callbackFunction is called from 
// the libary when some event occurs.  So that 
// means the actual method "NonAsync()" is called!
} 

The logic in the library that calls back this delgate looks like this

Example.Question.Library{
public ...{
    public ... SomeMethod(Delegate func){
        func.DynamicInvoke();
    }
}
}

this works just fine. What I need is to be able to call the Delegate from the library asynchronously.

need some help getting there

So i want something that looks like this...

...from the library which calls the delegate...

public ... SomeMethod(Delegate func){
        await func.DynamicInvoke();
    }

... from the consumer of the library which defines the delegate ...

Example.Question.Base{
    public static class Consumer{
        // ...

        public static async Task<T> Go(){
            // ...
            callbackFunction = await Async;
            // ...
        }

        public static async Task<bool> Async()
        {
            // Do some work ...
            return await Task.FromResult<bool>(false);
        }
    }
}

But the issue is I get a compiler error saying "Cannot await 'method group'"

enter image description here

Robert Green MBA
  • 1,834
  • 1
  • 22
  • 45
  • 1
    "What I need is to be able to call the Delegate from the library asynchronously" - what *exactly* do you mean by that? An asynchronous delegate is a delegate that you call, and it returns a `Task` of some kind. It's not the *call* that's asynchronous - it's the processing within the delegate. – Jon Skeet Jun 10 '18 at 08:43
  • 2
    Note that `Async` returns a `Task` not a `bool`, so it's not appropriate for `callbackFunction`. I suspect that the heart of the problem here isn't the code so much as how you're thinking about asynchrony. – Jon Skeet Jun 10 '18 at 08:45
  • 1. I'm trying to call the delegate using the await/async model. So I need something that looks like `callbackFunction = await Async;` I put the code example above. 2. I'm also simply showing in the above code example that I am able to accomplish calling a delegate w/o await/async but my question is simply (please excuse me if I worded it a little incorrectly) is how can I call a delegate using `await`? – Robert Green MBA Jun 10 '18 at 08:49
  • 1
    `await` isn't specifically part of how you call a delegate. If your delegate returns a task, you await *that*. That's why `await Async` doesn't work - you're thinking about where the asynchrony comes in a bit wrongly. You need to be thinking about "How can I make my delegate return a task?" (So the delegate *type* needs to declare that it returns a task, e.g. `Task`.) You can then call the delegate, and await the result. – Jon Skeet Jun 10 '18 at 08:55
  • My delegate is a `Task` ... and I still get the error – Robert Green MBA Jun 10 '18 at 09:43
  • 1
    `callbackFunction = await Async` doesn't make sense. Without the await, you're assigning a compatible method group to the delegate, but you can't put an await before a method group. If anything, assign a lambda `callback = async x => await Async();` but the delegate definition would have to be updated to return Task and not bool and that's not really gonna work in your dynamic invoke case. – pinkfloydx33 Jun 10 '18 at 09:53
  • ok, thanks @pinkfloydx33 so given that I need `dynamic invoke` and need to potentially assign a lambda (which I just tested and it failed) - what do you think I should do? (I am willing to pay for the answer) :-) – Robert Green MBA Jun 10 '18 at 10:18
  • 1
    You're probably going to have to settle for synchronous behavior. Your third party library is already enforcing that on you. Your call back could always do something like Task.Run and then wait (block) for the result. But that feels real shady and I wouldn't recommend it. The library authors expect your callback to be synchronous. Also: please don't offer payment on s/o – pinkfloydx33 Jun 10 '18 at 10:24
  • @pinkfloydx33 I am the author of the library and I would like it to call back asynchronously... – Robert Green MBA Jun 10 '18 at 11:09
  • 3
    Again, you need to work out *exactly* what you mean by "I would like it to call back asynchronously". At the moment it's not clear what you mean, and that may be because you're not sure yourself. (And that's entirely understandable - asynchrony is complex.) I would start off by trying to work out what it would all look like *without* any dynamic invocation, and what you want the effects to be - you can move on from there. – Jon Skeet Jun 10 '18 at 11:19
  • I mean if you look at my code I sure we're able to accomplish calling a delegate nona synchronously, without calling await... What I need to be able to do is to call that function using await... – Robert Green MBA Jun 10 '18 at 16:39
  • `await` is nothing to do with calling functions, you don't "call a function using await" so the question doesn't make sense. You await an awaitable, which is almost always a Task or a Task. Whether that awaitable is a variable in the same scope or the result of a method doesn't matter, because await isn't a modification to the calling syntax. I'm echoing the sentiment that the question isn't clear because the premise is faulty. – Tom W Jun 10 '18 at 19:49

1 Answers1

3

Just use something like that for example:

public static class Consumer
    {

        public static async Task<T> Go<T>()
        {
            var someLibrary = new SomeLibrary();
            return await someLibrary.SomeMethod(Async<T>);
        }

        public static async Task<T> Async<T>()
        {
            return await Task.FromResult(default(T));
        }
    }

public class SomeLibrary
    {
        public async Task<T> SomeMethod<T>(Func<Task<T>> func)
        {
            return await func.Invoke();
        }
    }
Lukasz Ożóg
  • 216
  • 3
  • 15