0

I'd like to add async delegate functions using Task. I want something like :

public delegate Task MethodHook(Object obj);
public MethodHook methodHook;

public async Task Task1(Object obj){
    await SomeTask1(obj);
    await Task.Delay(600);
}

public async Task Task2(Object obj){
    await SomeTask2(obj);
    await Task.Delay(600);
}
//...
void Foo(){
    methodHook+=Task1;
    methodHook+=Task2;
}

public async Task InvokeMethods(Object obj){
    await methodHook?.Invoke();
    Console.WriteLine("Done!");
}

So when I call InvokeMethods, SomeTask1 is called, wait until SomeTask1 completion, wait for 600ms, SomeTask2 is called, wait until SomeTask2 completion, wait for 600ms, and finally print "Done!". How can I make this work? I cannot use methodHook.BeginInvocation(obj,null,null); for some reason. Is there any solution?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
  • 2
    `wait for 600ms` - not really, because you don't await the `Delay`. – GSerg Sep 28 '22 at 10:18
  • Does this answer your question? [Creating/initializing task without starting it immediately](https://stackoverflow.com/questions/68692724/creating-initializing-task-without-starting-it-immediately) – GSerg Sep 28 '22 at 10:25
  • 2
    `foreach(var dgate in methodHook?.GetInvocationList()) await ((MethodHook)dgate).Invoke(obj);` [?](https://dotnetfiddle.net/eF84zU) – Selvin Sep 28 '22 at 10:32
  • 1
    @GSerg yeah forgot to add await keyword. my mistake. – user18818953 Sep 28 '22 at 11:38
  • @Selvin It works, but sometimes it returns error. Gonna find out why. Huge Thanks!! – user18818953 Sep 28 '22 at 11:39
  • Related: [How do I await events in C#?](https://stackoverflow.com/questions/27761852/how-do-i-await-events-in-c) – Theodor Zoulias Sep 28 '22 at 11:46

1 Answers1

2

I would not recommend using multicast delegates for this, even if it is possible to do, as it would likely be confusing for most readers. In depth knowledge of multi cast delegates is fairly rare in my experience.

My recommendation would be to create a specialized class, something like:

public class MyMulticastAsyncDelegate<T>
{
    private readonly IReadOnlyList<Func<T, Task>> invocationList;
    public MyMulticastAsyncDelegate() : this(new List<Func<T, Task>>()) { }
    public MyMulticastAsyncDelegate(IEnumerable<Func<T, Task>> invocationList) => this.invocationList = invocationList.ToArray();

    public static MyMulticastAsyncDelegate<T> operator +(MyMulticastAsyncDelegate<T> self, Func<T, Task> item) => new (self.invocationList.Append(item));
    public static MyMulticastAsyncDelegate<T> operator -(MyMulticastAsyncDelegate<T> self, Func<T, Task> item) => new (self.invocationList.Except(new []{item}));

    public async Task Invoke(T argument)
    {
        foreach (var func in invocationList)
        {
            await func(argument);
        }
    }
}

Used like

var del = new MyMulticastAsyncDelegate<int>();
del += async (i) => await Task.Delay(i);
await del.Invoke(100);

This should hopefully give any reader a hint that there is something special going on that is different from a regular event, and I hope most would be able to read the code and figure out what is going on fairly quickly.

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • Does this code include delegate function, not only task.delay? How can I add delegate with this? – user18818953 Sep 28 '22 at 12:00
  • @user18818953 You can add any `Func` delegate, `async (i) => await Task.Delay(i)` is just an example. You could ofc replace the `Func` with any custom delegate, But I see little reason to do so. – JonasH Sep 28 '22 at 12:05