I have the following WCF service:
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;
}
}
And this:
public class FooFactory
{
private IComponentContext _componentContext;
public FooFactory(Owned<IComponentContext> componentContext)
{
_componentContext = componentContext.Value;
}
public Foo Create()
{
return _componentContext.Resolve<Foo>();
}
}
The registration looks like this:
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();
}
Basically, I have an operation that returns to the caller right away, while the task I started continues in the background. Surprisingly, this did not terminate the task when the request "completed" - I would have thought that it would.
FooFactory needs to create Foo dynamically and that's why it takes a dependency on IComponentContext(or ILifetimeScope - is there a difference?). When I take a dependency on IComponentContext directly or by using a delegate as in the commented out code, an exception occurs saying the IComponentContext instance is disposed. I'm guessing this is because the parent ILifetimeScope which was associated with the request (via Autofac.WCF) is disposed. But if I take a dependency on Owned instead, the exception does not occur. So it seems the code is working and doing what I want.
However, the question is, is this safe?
I mean, the request completes and response is returned to the caller first and the instance resolution occurs afterwards from the context that was created for the request. As far as Autofac is concerned, the scope for the request is gone. Imagine we were deep in the nested scope when FooFactory call came.
What are the implications?