This class acts as an asynchronous event handler that will execute all attached tasks in an async/await context. Requires Nuget Immutables
. Example usage:
class MyEventArgs : EventArgs {}
async Task SomeAsyncMethodAobject src, EventArgs args) {
Console.WriteLine("Task A...");
await Task.Delay(2000);
}
async Task SomeAsyncMethodB(object src, EventArgs args) {
Console.WriteLine("Task B...");
await Task.Delay(1000);
}
static async Task Main(string[] args) {
AsyncEvent<MyEventArgs> Events;
Events = new AsyncEvent<MyEventArgs>();
Events += SomeAsyncMethodA;
Events += SomeAsyncMethodB;
await Events?.InvokeAsync(this, new MyEventArgs());
// Use below to discard task and not await event task to finish.
// _ = Events?.InvokeAsync(this, new MyEventArgs()).ConfigureAwait(false);
}
Source for the AsyncEvent<EventArgsT>
class:
// T is the EventArgs class type to pass to the callbacks on Invoke.
public class AsyncEvent<T> where T : EventArgs {
// List of task methods to await.
public ImmutableList<Func<object, T, Task>> Invokables;
// on += add new callback method to AsyncEvent.
public static AsyncEvent<T> operator+(AsyncEvent<T> source, Func<object, T, Task> callback) {
if (callback == null) throw new NullReferenceException("Callback is null! <AsyncEvent<T>>");
if (source == null) return null;
if (source.Invokables == null) source.Invokables = ImmutableList<Func<object, T, Task>>.Empty;
source.Invokables = source.Invokables.Add(callback);
return source;
}
// on -= remove existing callback from AsyncEvent.
public static AsyncEvent<T> operator -(AsyncEvent<T> source, Func<object, T, Task> callback) {
if (callback == null) throw new NullReferenceException("Callback is null! <AsyncEvent<T>>");
if (source == null) return null;
source.Invokables = source.Invokables.Remove(callback);
return source;
}
// Invoke the tasks asynchronously with a cancelation token.
public async Task InvokeAsync(object source, T evArgs, CancellationToken token) {
List<Task> tasks = new List<Task>();
if (Invokables != null)
foreach (var callback in Invokables)
if (!token.IsCancellationRequested)
tasks.Add(callback(source, evArgs));
await Task.WhenAll(tasks.ToArray());
}
// Invoke the tasks asynchronously.
public async Task InvokeAsync(object source, T evArgs) {
List<Task> tasks = new List<Task>();
if (Invokables != null)
foreach (var callback in Invokables)
tasks.Add(callback(source, evArgs));
await Task.WhenAll(tasks.ToArray());
}
}
Is there anything wrong with this asynchronous paradigm?
AsyncEvent
do you have? What jobs are they doing on the event was fired? What data is passed by Args? How often the event is fired, ~times/sec, peak/avg? Why I'm asking: It looks like you've solved some problem in a wrong way. \$\endgroup\$