using System.Threading.Channels; namespace RegexBot.Services.SharedEventService; /// /// Implements a queue which any service or module may send objects into, /// which are then sent to subscribing services and/or modules. Allows for simple, /// basic sharing of information between separate parts of the program. /// class SharedEventService : Service { private readonly Channel _items; //private readonly Task _itemPropagationWorker; internal SharedEventService(RegexbotClient bot) : base(bot) { _items = Channel.CreateUnbounded(); _ = Task.Factory.StartNew(ItemPropagator, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); } // Hooked (lock this on self) internal event RegexbotClient.IncomingSharedEventHandler? Subscribers; internal async Task PushSharedEventAsync(ISharedEvent ev) { await _items.Writer.WriteAsync(ev); } private async Task ItemPropagator() { while (true) { var ev = await _items.Reader.ReadAsync(); Delegate[]? subscribed; lock (this) { subscribed = Subscribers?.GetInvocationList(); if (subscribed == null || subscribed.Length == 0) return; } foreach (var handler in subscribed) { // Fire and forget! _ = Task.Run(async () => { try { await (Task)handler.DynamicInvoke(ev)!; } catch (Exception ex) { Log("Unhandled exception in shared event handler:" + ex.ToString()); } }); } } } }