You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

永不完成的TaskCompletionSource是否会引发内存泄漏问题?

结论

你提供的写法确实存在内存泄漏风险,风险的核心原因来自原始长耗时Task的引用链持有。


泄漏原因说明

  • 调用MuteOnDestroy扩展方法时,内部创建的TaskCompletionSource<T>(以下简称TCS)会被ContinueWith的回调闭包捕获,而这个回调会被原始的LongAction返回的Task持有,直到LongAction执行完成。
  • 被await的TCS.Task会持有RunExample异步方法的状态机实例,状态机作为实例方法的状态容器,又会持有你的组件实例本身。
  • 只要LongAction还未执行完成,哪怕destroyToken已经被标记为取消、你的组件已经没有其他外部引用,整条引用链(LongAction Task → ContinueWith回调 → TCS → TCS.Task → 异步状态机 → 组件实例)都会被GC标记为存活,不会被回收,产生内存泄漏。如果LongAction永久不完成,这段内存会被永久占用。
  • 就算LongAction最终执行完成,回调发现token已取消、未给TCS设置任何状态,此时TCS没有其他引用的情况下才会和状态机一起被回收,但在LongAction运行的这段时间内,泄漏依然存在。

优化方案

你当前的实现思路是用「永远不完成的Task」阻止后续逻辑执行,这个思路本身就容易引发泄漏问题。更合理的实现是让所有Task正常结束,主动判断组件状态决定是否执行后续逻辑,既满足需求也不会产生泄漏,示例如下:

// 扩展方法:吞掉取消异常,返回默认值
public static class TaskExtension
{
    public static async Task<T> SuppressCancellation<T>(this Task<T> task)
    {
        try
        {
            return await task;
        }
        catch (OperationCanceledException)
        {
            return default;
        }
    }
}

// 业务代码调整
private CancellationTokenSource destroyTokenSource = new CancellationTokenSource();

private async void RunExample()
{
    // 把销毁token传给长耗时任务,支持提前终止任务执行
    var result = await LongAction(destroyTokenSource.Token).SuppressCancellation();
    // 主动判断组件是否已销毁,决定是否执行后续逻辑
    if (destroyTokenSource.IsCancellationRequested) return;
    
    // ... 只有组件未销毁才会执行的后续逻辑
}

// 长耗时任务支持传入取消token,内部可以在关键点判断token状态提前终止
private async Task<bool> LongAction(CancellationToken token = default)
{
    // 长耗时逻辑中插入token判断,比如:
    // await Task.Delay(5000, token);
    // if (token.IsCancellationRequested) return false;
    return true;
}

另外注意两点:

  1. 你原有的实现只是忽略了长耗时任务的结果,并没有真的停止LongAction本身的执行,把CancellationToken传入LongAction内部才能实现任务的提前终止,减少不必要的性能损耗。
  2. 尽量避免使用async void方法,除非是UI事件处理器这类场景,async void方法的未处理异常会直接抛出到同步上下文,容易导致进程崩溃,建议改为async Task。

内容的提问来源于stack exchange,提问作者Dem0n13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 10:45:03