C# Autofac不处理后台任务
我有一个任务需要在后台单独的线程中运行,我正在使用signar报告进度。这在一段时间前就起作用了,我对代码做了一些修改,但现在我完全不知道我收到了什么错误: 从请求实例的作用域中看不到标记与“AutofacWebRequest”匹配的作用域。这通常表示单实例组件或类似场景正在请求根据HTTP请求注册的组件。在web集成下,始终从DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime请求依赖项,而不是从容器本身 非常感谢您的帮助C# Autofac不处理后台任务,c#,autofac,C#,Autofac,我有一个任务需要在后台单独的线程中运行,我正在使用signar报告进度。这在一段时间前就起作用了,我对代码做了一些修改,但现在我完全不知道我收到了什么错误: 从请求实例的作用域中看不到标记与“AutofacWebRequest”匹配的作用域。这通常表示单实例组件或类似场景正在请求根据HTTP请求注册的组件。在web集成下,始终从DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime请求依赖项,而不是从容器本身 非常感谢您
public ActionResult DoAction(IEnumerable<string> items){
//...
Func<CancellationToken, Task> taskFunc = CancellationToken => performAction(items);
HostingEnvironment.QueueBackgroundWorkItem(taskFunc);
//...
}
private async Task performAction(IEnumerable<string> items){
var svc = AutofacDependencyResolver.Current.AppicationContainer.BeginLifetimeScope().Resolve<MyService>();
svc.Method(items);
}
public class MyService{
private EntityContext db;
public MyService(EntityContext db){
this.db = db;
}
}
在my Startup.Container.cs文件中:
builder.RegisterType<MyService>().As<MyService>().InstancePerLifetimeScope();
builder.RegisterType<EntityContext>().InstancePerRequest();
最近,我使用这个和这个的帮助实现了类似的东西。您需要创建一个新的生命周期范围-听起来像是在web应用程序中这样做,因此您需要通过下面的每个请求标记示例来创建范围 另一个非StackOverflow提供了类似的建议
public Task Run<T>(Action<T> action)
{
Task.Factory.StartNew(() =>
{
using (var lifetimeScope = _container.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag))
{
var service = lifetimeScope.Resolve<T>();
action(service);
}
});
return Task.FromResult(0);
}
最近,我使用这个和这个的帮助实现了类似的东西。您需要创建一个新的生命周期范围-听起来像是在web应用程序中这样做,因此您需要通过下面的每个请求标记示例来创建范围 另一个非StackOverflow提供了类似的建议
public Task Run<T>(Action<T> action)
{
Task.Factory.StartNew(() =>
{
using (var lifetimeScope = _container.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag))
{
var service = lifetimeScope.Resolve<T>();
action(service);
}
});
return Task.FromResult(0);
}
基于上述代码的更新答案: 用法:
public class ServiceModule :Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<AutoFac.AsyncRunner>().As<AutoFac.IAsyncRunner>().SingleInstance();
}
}
public class Controller
{
private AutoFac.IAsyncRunner _asyncRunner;
public Controller(AutoFac.IAsyncRunner asyncRunner)
{
_asyncRunner = asyncRunner;
}
public void Function()
{
_asyncRunner.Run<IService>((cis) =>
{
try
{
//do stuff
}
catch
{
// catch stuff
throw;
}
});
}
}
界面:
public interface IAsyncRunner
{
Task Run<T>(Action<T> action);
}
班级:
public class AsyncRunner : IAsyncRunner
{
private ILifetimeScope _lifetimeScope { get; set; }
public AsyncRunner(ILifetimeScope lifetimeScope)
{
//Guard.NotNull(() => lifetimeScope, lifetimeScope);
_lifetimeScope = lifetimeScope;
}
public Task Run<T>(Action<T> action)
{
Task.Factory.StartNew(() =>
{
using (var lifetimeScope = _lifetimeScope.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag))
{
var service = lifetimeScope.Resolve<T>();
action(service);
}
});
return Task.FromResult(0);
}
}
基于上述代码的更新答案: 用法:
public class ServiceModule :Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<AutoFac.AsyncRunner>().As<AutoFac.IAsyncRunner>().SingleInstance();
}
}
public class Controller
{
private AutoFac.IAsyncRunner _asyncRunner;
public Controller(AutoFac.IAsyncRunner asyncRunner)
{
_asyncRunner = asyncRunner;
}
public void Function()
{
_asyncRunner.Run<IService>((cis) =>
{
try
{
//do stuff
}
catch
{
// catch stuff
throw;
}
});
}
}
界面:
public interface IAsyncRunner
{
Task Run<T>(Action<T> action);
}
班级:
public class AsyncRunner : IAsyncRunner
{
private ILifetimeScope _lifetimeScope { get; set; }
public AsyncRunner(ILifetimeScope lifetimeScope)
{
//Guard.NotNull(() => lifetimeScope, lifetimeScope);
_lifetimeScope = lifetimeScope;
}
public Task Run<T>(Action<T> action)
{
Task.Factory.StartNew(() =>
{
using (var lifetimeScope = _lifetimeScope.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag))
{
var service = lifetimeScope.Resolve<T>();
action(service);
}
});
return Task.FromResult(0);
}
}
我做了一些类似于@Chima Osuji的事情,但我认为他的回答有问题,所以我将描述我的解决方案并解释它
public class BackgroundTaskFactory : IBackgroundTaskFactory
{
private ILifetimeScope lifetimeScope;
public BackgroundTaskFactory(ILifetimeScope lifetimeScope)
{
this.lifetimeScope = lifetimeScope;
}
public Task Run<T>(Action<T> action)
{
Task task = Task.Factory.StartNew(() =>
{
using (var lifetimeScope = this.lifetimeScope.BeginLifetimeScope())
{
var service = lifetimeScope.Resolve<T>();
action(service);
}
});
return task;
}
}
必须指出,我的Run方法返回在task.Factory.StartNew上创建的任务。这样,有人等待结果,他得到了正确的任务。在其他解决方案中,它们返回Task.FromResult0,返回一个虚拟任务
BeginLifetimeScope创建一个新作用域作为注入作用域的子作用域。如果注入的作用域是与web请求关联的InstancePerLifetimeScope,那么一旦web请求作用域被释放,这个新作用域也将被释放,并且它将出错。子作用域不能比其父作用域存在更长的时间。解决方案将BackgroundTaskFactory注册为singleton。当您这样做时,注入的生存期作用域将是根作用域,在释放应用程序之前,它不会被释放
containerBuilder.RegisterType我做了一些类似于@Chima Osuji的事情,但我认为他的回答有问题,所以我将描述我的解决方案并解释它
public class BackgroundTaskFactory : IBackgroundTaskFactory
{
private ILifetimeScope lifetimeScope;
public BackgroundTaskFactory(ILifetimeScope lifetimeScope)
{
this.lifetimeScope = lifetimeScope;
}
public Task Run<T>(Action<T> action)
{
Task task = Task.Factory.StartNew(() =>
{
using (var lifetimeScope = this.lifetimeScope.BeginLifetimeScope())
{
var service = lifetimeScope.Resolve<T>();
action(service);
}
});
return task;
}
}
必须指出,我的Run方法返回在task.Factory.StartNew上创建的任务。这样,有人等待结果,他得到了正确的任务。在其他解决方案中,它们返回Task.FromResult0,返回一个虚拟任务
BeginLifetimeScope创建一个新作用域作为注入作用域的子作用域。如果注入的作用域是与web请求关联的InstancePerLifetimeScope,那么一旦web请求作用域被释放,这个新作用域也将被释放,并且它将出错。子作用域不能比其父作用域存在更长的时间。解决方案将BackgroundTaskFactory注册为singleton。当您这样做时,注入的生存期作用域将是根作用域,在释放应用程序之前,它不会被释放
containerBuilder.RegisterType你读了吗?你读了吗?AsyncRunner的代码在这里:AsyncRunner的代码在这里: