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

Dotnet 6中Transient服务使用ActivitySource避免内存泄漏的咨询

在Transient服务中安全使用ActivitySource的解决方案

先澄清一个关键误解

你代码里的private static readonly ActivitySource不会每次实例化服务都创建新实例——静态字段属于类本身,不管创建多少个MyTransientService实例,这个ActivitySource只会被初始化一次。但如果项目中有大量这类定义了专属静态ActivitySource的Transient服务,长期运行后可能因累积的追踪资源导致内存增长。


方案1:为服务注入Singleton的ActivitySource

直接将每个服务对应的ActivitySource注册为单例,通过依赖注入使用,这是最直接的实现方式:

  1. 在DI容器中注册单例ActivitySource:
// Program.cs 中配置服务
builder.Services.AddSingleton(new ActivitySource(nameof(MyTransientService)));
builder.Services.AddSingleton(new ActivitySource(nameof(AnotherTransientService)));
  1. 在Transient服务中注入使用:
public class MyTransientService: IMyTransientService
{
    private readonly IOtherService _otherService;
    private readonly ActivitySource _activitySource;

    public MyTransientService(IOtherService otherService, ActivitySource activitySource)
    {
        _otherService = otherService;
        _activitySource = activitySource;
    }

    public async Task<SomeClass> GetTransactionsFromMeniga(SomeOtherClass testObj)
    {
        using var thisActivity = _activitySource.StartActivity("New activity");
        // 业务逻辑代码
    }
}

线程安全说明:ActivitySource是微软官方设计为线程安全的类型,多线程并发调用StartActivity不会产生线程安全问题。


方案2:用统一工厂管理所有ActivitySource

如果项目中有大量Transient服务需要使用ActivitySource,可以创建一个Singleton工厂类来集中管理,避免重复注册:

  1. 实现工厂类:
public interface IActivitySourceFactory
{
    ActivitySource GetActivitySource(string sourceName);
}

public class ActivitySourceFactory : IActivitySourceFactory
{
    private readonly Dictionary<string, ActivitySource> _sourceCache = new();
    private readonly object _lockObj = new();

    public ActivitySource GetActivitySource(string sourceName)
    {
        if (_sourceCache.TryGetValue(sourceName, out var source))
        {
            return source;
        }

        // 双重检查锁定保证线程安全
        lock (_lockObj)
        {
            if (!_sourceCache.TryGetValue(sourceName, out source))
            {
                source = new ActivitySource(sourceName);
                _sourceCache.Add(sourceName, source);
            }
        }
        return source;
    }
}
  1. 注册工厂到DI容器:
// Program.cs 中配置服务
builder.Services.AddSingleton<IActivitySourceFactory, ActivitySourceFactory>();
  1. 在Transient服务中使用工厂:
public class MyTransientService: IMyTransientService
{
    private readonly IOtherService _otherService;
    private readonly ActivitySource _activitySource;

    public MyTransientService(IOtherService otherService, IActivitySourceFactory sourceFactory)
    {
        _otherService = otherService;
        _activitySource = sourceFactory.GetActivitySource(nameof(MyTransientService));
    }

    public async Task<SomeClass> GetTransactionsFromMeniga(SomeOtherClass testObj)
    {
        using var thisActivity = _activitySource.StartActivity("New activity");
        // 业务逻辑代码
    }
}

额外注意事项

  • ActivitySource的设计目标是长期存活的单例对象,官方推荐每个业务模块/服务只创建一个实例,而非每次使用都新建。
  • 若之前的代码中存在大量分散的静态ActivitySource,换成依赖注入的单例方式后,能更清晰地管理实例生命周期,也便于后续排查内存相关问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 20:20:29