C# Autofac - InstancePerLifetimeScope 和多线程:并发问题
C# Autofac - InstancePerLifetimeScope and multi thread: concurrency issues
我有一个使用 Autofac 的 WCF 服务 .net framework 4.0。
然后我有几个依赖是这样解决的:
builder.RegisterType<LogicA>().As<ILogicA>().InstancePerLifetimeScope();
我在 class 中有一个操作,其中通过参数注入依赖项,因为 class 本身也在与依赖项相同的 class 上被引用:
public void DoStuff(List<string> items, ILogicA logicA){
foreach (var item in items)
{
System.Threading.ThreadPool.QueueUserWorkItem(queueUserWorkItem =>
{
logicA.DoOtherStuff(item);
});
}}
发生的事情是在 DoOtherStuff 方法内部,它调用其他 classes,其中一些具有为集合中的每个项目填充的状态(属性),最后数据保存在数据库中.
最后,当项目集合开始有一些项目(超过 6 或 7)时,有时我开始收到主键违规错误(这使用引擎盖下的 SQL 服务器)并且如果我打开一个 SQL 分析器,我可以看到对同一 ID 的调用超过 1 个,而如果我将日志记录放在上面的 foreach 块的开头,我就看不到任何重复的东西,这让我认为也许这个 logicA 参数原来不是线程安全的。
我应该在我的 QueueUserWorkItem 块中解决这种对需求的依赖性,还是我在这里遗漏了其他任何东西?
感谢您的帮助
在不了解更多上下文的情况下很难说,但这似乎是一个经典的工作单元场景,您可能希望为每个后台操作分配生命周期范围。
public void DoStuff(List<string> items, ILifetimeScope scope){
foreach (var item in items)
{
var newScope = scope.BeginLifetimeScope();
System.Threading.ThreadPool.QueueUserWorkItem(queueUserWorkItem =>
{
using (newScope)
{
var logicA = newScope.Resolve<ILogicA>();
logicA.DoOtherStuff(item);
}
});
}}
即使这不完全正确,通常明智的做法是不要在任何工作单元之间共享一个生命周期范围;共享状态可能会有点奇怪。
我有一个使用 Autofac 的 WCF 服务 .net framework 4.0。
然后我有几个依赖是这样解决的:
builder.RegisterType<LogicA>().As<ILogicA>().InstancePerLifetimeScope();
我在 class 中有一个操作,其中通过参数注入依赖项,因为 class 本身也在与依赖项相同的 class 上被引用:
public void DoStuff(List<string> items, ILogicA logicA){
foreach (var item in items)
{
System.Threading.ThreadPool.QueueUserWorkItem(queueUserWorkItem =>
{
logicA.DoOtherStuff(item);
});
}}
发生的事情是在 DoOtherStuff 方法内部,它调用其他 classes,其中一些具有为集合中的每个项目填充的状态(属性),最后数据保存在数据库中.
最后,当项目集合开始有一些项目(超过 6 或 7)时,有时我开始收到主键违规错误(这使用引擎盖下的 SQL 服务器)并且如果我打开一个 SQL 分析器,我可以看到对同一 ID 的调用超过 1 个,而如果我将日志记录放在上面的 foreach 块的开头,我就看不到任何重复的东西,这让我认为也许这个 logicA 参数原来不是线程安全的。
我应该在我的 QueueUserWorkItem 块中解决这种对需求的依赖性,还是我在这里遗漏了其他任何东西?
感谢您的帮助
在不了解更多上下文的情况下很难说,但这似乎是一个经典的工作单元场景,您可能希望为每个后台操作分配生命周期范围。
public void DoStuff(List<string> items, ILifetimeScope scope){
foreach (var item in items)
{
var newScope = scope.BeginLifetimeScope();
System.Threading.ThreadPool.QueueUserWorkItem(queueUserWorkItem =>
{
using (newScope)
{
var logicA = newScope.Resolve<ILogicA>();
logicA.DoOtherStuff(item);
}
});
}}
即使这不完全正确,通常明智的做法是不要在任何工作单元之间共享一个生命周期范围;共享状态可能会有点奇怪。