WeakTypes - Axvser/MinimalisticWPF GitHub Wiki

类名 描述 使用场景
WeakCache<TTargetKey, TCacheKey> 弱引用字典式缓存 若存在对象集合,且需要周期性地遍历集合,使用与对象相关联的上下文缓存执行后续操作,那么可以使用这个类以在不阻止GC的前提下,维护对象与缓存的联系
WeakDelegate<TDelegate> 弱引用事件处理器集合 用于不希望阻止订阅者被GC回收的事件处理器
WeakQueue<T> 弱引用先进先出集合 需要弱引用队列语义时
WeakStack<T> 弱引用后进先出集合 需要弱引用堆栈语义时

WeakCache<TTargetKey, TCacheKey>

注意,若您永远不调用 ForeachCache 操作,也不调用 TryGetCache 操作,那么即便对象与对应的缓存能被回收,其弱引用仍会占据一定空间,这是不好的实践

// 管理所有活跃的WebSocket连接
var wsCache = new WeakCache<WebSocketClient, SessionState>();

// 新连接建立时
wsCache.AddOrUpdate(client, new SessionState {
    UserId = userId,
    ConnectTime = DateTime.Now
});

// 定时任务:向所有连接发送心跳
wsCache.ForeachCache((client, state) => 
{
    if (DateTime.Now - state.LastHeartbeatTime > HeartbeatInterval)
    {
        client.Send(new HeartbeatMessage());
        state.LastHeartbeatTime = DateTime.Now;
    }
});

WeakDelegate

注意,不要滥用这个类,如果您使用诸如 KeyEventHandler 这样的事件,那它自身就是弱事件模型,与 WeakDelegate 结合使用将导致意外的GC回收

// 创建弱事件处理器集合
var weakHandlers = new WeakDelegate<EventHandler<EventArgs>>();

// 添加处理器
weakHandlers.AddHandler(MyEventHandler);

// 调用所有存活的处理器
var invocationList = weakHandlers.GetInvocationList();
invocationList?.Invoke(this, EventArgs.Empty);

// 移除处理器
weakHandlers.RemoveHandler(MyEventHandler);

WeakQueue

与正常的队列用起来差不多,只是对于其中已经被GC回收的部分,会直接略过,例如 A → B → C,我本应取出 A → B → C,可由于B已被GC回收,我两次取出即可拿到 A → C 而无需取三次

// 创建弱引用队列
var queue = new WeakQueue<MyResource>();

// 添加项目
queue.Enqueue(new MyResource());
queue.EnqueueRange(resourceList);

// 处理项目
while (queue.TryDequeue(out var resource))
{
    resource.DoSomething();
}

// 检查内容
if (queue.TryPeek(out var nextItem))
{
    // 预览下一个项目
}

WeakStack

与正常的栈用起来差不多,只是对于其中已经被GC回收的部分,会直接略过,例如 A → B → C ,我原本应取出 C → B → A ,可由于B已被GC回收,我两次出栈操作即可返回 C → A 而无需三次出栈

// 创建弱引用堆栈
var stack = new WeakStack<MyResource>();

// 压入项目
stack.Push(new MyResource());
stack.PushRange(resourceList);

// 处理项目
while (stack.TryPop(out var resource))
{
    resource.DoSomething();
}

// 检查顶部项目
if (stack.TryPeek(out var topItem))
{
    // 查看顶部项目
}
⚠️ **GitHub.com Fallback** ⚠️