首页 > 解决方案 > Autofac System.ArgumentNullException:值不能为空。参数名称:上下文

问题描述

我为每个匹配的生命周期范围创建了 autofac 实例,并在父范围已经存在但出现异常的情况下创建子范围。

请参阅下面的代码和堆栈跟踪。

代码

public static class App {
   private static AsyncLocal<ILifetimeScope> _upperScope;

   public static AsyncLocal<int> Number = new AsyncLocal<int>();

   public static ILifetimeScope NewScope(IContainer container) {
        if (_upperScope?.Value != null)
           return _upperScope.Value.BeginLifetimeScope();

        _upperScope = new AsyncLocal<ILifetimeScope> {Value = container.BeginLifetimeScope("test")};
        _upperScope.Value.CurrentScopeEnding += (sender, args) => _upperScope.Value = null;
        return _upperScope.Value;
   }
}

[Fact]
public void Test1() {
     var containerBuilder = new ContainerBuilder();
     containerBuilder.RegisterType<ClassOne>().AsSelf().InstancePerMatchingLifetimeScope("test");
     var container = containerBuilder.Build();

     var tasks = new List<Task>();

     tasks.Add(Task.Run(() => {
         using (var scope = App.NewScope(container)) {
             scope.Resolve<ClassOne>();
         }
     }));

     tasks.Add(Task.Run(() => {
         using (var scope = App.NewScope(container)) {
             scope.Resolve<ClassOne>();
         }
     }));

     Task.WaitAll(tasks.ToArray());
}

单击此处获取堆栈跟踪

标签: c#multithreadingautofac

解决方案


您收到此错误是因为您分配了AsyncLocal<T>不止一次而不是仅分配一次。您应该将其实例化一次,然后Value多次分配该属性,该属性对于每个线程都是唯一的。

IE :

private static AsyncLocal<ILifetimeScope> _upperScope = new AsyncLocal<ILifetimeScope>();

进而

_upperScope.Value = container.BeginLifetimeScope("test");

推荐阅读