进程内队列? 为啥不用 Channel
https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.channels.channel?view=net-8.0另外,如果是事件总线,可以考虑引入泛型之类的花样类型匹配订阅筛选器
这是自用的事件总线实现,目前大规模用在工作生产环境和玩具项目,未发现明显性能瓶颈
IEventBus.cs
```
public interface IEventBus
{
bool Subscript<T>(Action<T> callBack);
bool UnSubscript<T>(Action<T> callBack);
bool Publish<T>();
bool Publish<T>(T obj);
}
```
AnyPublishEvent.cs
```
/// <summary>
/// 任何事件发布,用于统计或通配
/// </summary>
[DisplayName("*")]
public record AnyPublishEvent(Type Type, object? Obj);
```
InProcessEventBusBase.cs
```
public abstract class InProcessEventBusBase(ILogger<InProcessEventBusBase> logger) : IEventBus
{
private readonly Dictionary<Type, HashSet<Delegate>> _dicTypeToHandlers = [];
public bool Subscript<T>(Action<T> callBack)
{
var type = typeof(T);
lock (_dicTypeToHandlers)
{
if (!_dicTypeToHandlers.TryGetValue(type, out var handlers))
{
handlers = _dicTypeToHandlers[type] = [];
}
return handlers.Add(callBack); // 忽略重复
}
}
public bool UnSubscript<T>(Action<T> callBack)
{
lock (_dicTypeToHandlers)
{
if (_dicTypeToHandlers.TryGetValue(typeof(T), out var handlers))
{
var unSubscript = handlers.Remove(callBack);
if (handlers.Count == 0) _dicTypeToHandlers.Remove(typeof(T));
return unSubscript;
}
return false;
}
}
public bool Publish<T>()
{
PublishInternal(new AnyPublishEvent(typeof(T), default));
return PublishInternal<T?>(default);
}
public bool Publish<T>(T obj)
{
PublishInternal(new AnyPublishEvent(typeof(T), obj));
return PublishInternal(obj);
}
private bool PublishInternal<T>(T eventValue)
{
var type = typeof(T);
Delegate[] subscripts;
lock (_dicTypeToHandlers)
{
if (!_dicTypeToHandlers.TryGetValue(type, out var handlers)) return false;
subscripts = [.. handlers];
}
foreach (var del in subscripts)
{
try
{
((Action<T>)del)(eventValue);
}
catch (Exception e)
{
logger.LogError(e, nameof(Publish));
}
}
return true;
}
}
```