我有以下WCF服务:
public class TimeService : ITimeService
{
private FooFactory _fooFactory;
public TimeService(FooFactory fooFactory)
{
_fooFactory = fooFactory;
}
public DateTime Now()
{
Foo result = null;
Stopwatch sw = new Stopwatch();
sw.Start();
Debug.Print($"[{Thread.CurrentThread.ManagedThreadId}] BEGIN Operation");
Task.Run<Foo>(() =>
{
Debug.Print($"[{Thread.CurrentThread.ManagedThreadId}] BEGIN Task {sw.ElapsedMilliseconds}ms");
Task.Delay(TimeSpan.FromSeconds(10)).Wait();
return _fooFactory.Create();
}).ContinueWith(x =>
{
try
{
Debug.Print($"[{Thread.CurrentThread.ManagedThreadId}] CONTINUE Task {sw.ElapsedMilliseconds}ms");
result = x.Result;
Debug.Print($"[{Thread.CurrentThread.ManagedThreadId}] CONTINUE Task {sw.ElapsedMilliseconds}ms, Result = {result}");
}
catch (Exception ex)
{
Debug.Print($"[{Thread.CurrentThread.ManagedThreadId}] CONTINUE Task {ex}");
}
});
Debug.Print($"[{Thread.CurrentThread.ManagedThreadId}] END Operation {sw.ElapsedMilliseconds}ms");
return result?.Now ?? DateTime.MinValue;
}
}
而且:
public class FooFactory
{
private IComponentContext _componentContext;
public FooFactory(Owned<IComponentContext> componentContext)
{
_componentContext = componentContext.Value;
}
public Foo Create()
{
return _componentContext.Resolve<Foo>();
}
}
注册如下:
AutofacHostFactory.Container = CreateContainer();
...
private IContainer CreateContainer()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Foo>().AsSelf();
builder.RegisterType<FooFactory>().AsSelf().InstancePerLifetimeScope();
//builder.Register(c => new FooFactory(c.Resolve<IComponentContext>()));
builder.RegisterType<TimeService>().As<ITimeService>().AsSelf();
return builder.Build();
}
基本上,我有一个操作立即返回给调用者,而我开始的任务在后台继续。令人惊讶的是,当请求“完成”时,这并没有终止任务 - 我本以为会这样做。
FooFactory需要动态创建Foo,这就是为什么它需要依赖IComponentContext(或ILifetimeScope - 有区别吗?)。 当我直接依赖IComponentContext或使用注释代码中的委托时,会发生一个异常,说明IComponentContext实例已被释放。我猜这是因为与请求相关联的父ILifetimeScope(通过Autofac.WCF)被处理掉了。但是,如果我依赖于Owned,则不会发生异常。所以看起来代码正在运行并做我想做的事。
然而,问题是,这样安全吗?
我的意思是,请求完成并且响应首先返回给调用者,之后实例解析从为请求创建的上下文发生。就Autofac而言,请求的范围已经消失。想象一下,当FooFactory调用来时,我们深深陷入了嵌套范围。
有什么影响?
答案 0 :(得分:1)
这个问题有许多隐含的问题,并且不可能做出简单的回答。因此,我将尝试解释一些表达的疑虑。
首先:IComponentContext和ILifetimeScope之间的区别是什么? 至于this question,
两个接口都提供标准的Resolve()操作 ILifetimeScope通过添加方法扩展IComponentContext 开始新的嵌套生命周期。
所以,鉴于不应该有任何性能损失,我总是使用ILifetimeScope,因为你可以根据需要打开嵌套范围。
要正确实例化组件,您需要一个有效的范围(或上下文,我会坚持使用&#34;范围&#34;对于其余的答案)。范围的好处在于,当Autofac将处理它们时,它将自动处理由它们解析的每个组件。
解析FooFactory的范围是WCF请求范围,它在请求完成时自动处理。
因此,您需要获取的例外情况是:上下文已被处理,无法再使用。
拥有和LT;&GT;正是出于这个目的而存在:为对象提供自治范围,因此当父范围关闭时它们不会被处理。
安全吗?是的,如果您在完成后致电处理,因为Autofac不知道何时需要处置。
作为参考(可能对其他读者而言),优秀的Autofac Lifetime Primer涵盖了您使用此工具时需要了解的所有内容。
让我补充一些关于实施可能存在缺陷的要点:
只需要一个拥有的&lt; ILifetimeScope&gt;而不是FooFactory并在任务完成时处理它。 如果您需要进一步的建议,请告诉我。
祝你好运!