using System.Collections.Generic;
using System.Threading.Tasks;
public class AsyncEvent<TEventArgs> where TEventArgs : EventArgs
private readonly List<Func<object, TEventArgs, Task>> invocationList;
private readonly object locker;
invocationList = new List<Func<object, TEventArgs, Task>>();
public static AsyncEvent<TEventArgs> operator +(
AsyncEvent<TEventArgs> e, Func<object, TEventArgs, Task> callback)
if (callback == null) throw new NullReferenceException("callback is null");
if (e == null) e = new AsyncEvent<TEventArgs>();
e.invocationList.Add(callback);
public static AsyncEvent<TEventArgs> operator -(
AsyncEvent<TEventArgs> e, Func<object, TEventArgs, Task> callback)
if (callback == null) throw new NullReferenceException("callback is null");
if (e == null) return null;
e.invocationList.Remove(callback);
public async Task InvokeAsync(object sender, TEventArgs eventArgs)
List<Func<object, TEventArgs, Task>> tmpInvocationList;
tmpInvocationList = new List<Func<object, TEventArgs, Task>>(invocationList);
foreach (var callback in tmpInvocationList)
await callback(sender, eventArgs);
public interface IEventContainer
AsyncEvent<EventArgs> SearchRequest { get; set; }
public class EventContainer: IEventContainer
public AsyncEvent<EventArgs> SearchRequest { get; set; }
public async static void Main()
IEventContainer container = new EventContainer();
container.SearchRequest += async (s, e) =>
System.Console.WriteLine("starting search");
await Task.Run(() => System.Console.WriteLine("searching"));
System.Console.WriteLine("search complete");
await container.SearchRequest.InvokeAsync(null, null);