我希望有关如何使用Ninject实现以下内容的建议:
我有一个多线程应用程序。它同时运行大约20个非常独立的线程。在应用程序启动时,我通过使用InThreadScope()通过Ninject将接口绑定到对象,并且一切正常。每个线程接收特定于其线程的对象(每个对象的构造函数实例化一些特定于线程的标志)。
每个线程所做的大部分工作都在等待数据存储完成进程。因此,为了进一步优化线程,我们在主要的20个线程中实现了Parallel.ForEach逻辑。我想让Paralell.ForEach生成的线程获得与其父线程相同的绑定。但是,我不能简单地将接口重新绑定到Parallel.ForEach中的适当对象,我根本不知道绑定对象是什么 - 在Paralell.ForEach中我只能使用接口。
在Paralell.ForEach启动并在循环中一般性地重新绑定它们之前,在运行时从内核检索绑定的正确方法是什么?
编辑:尝试包含详细的逻辑/伪代码:
每个线程一旦启动就会执行以下操作:
Kernel.Bind<ILoggingContext>().To<Application1LoggingContext>().InThreadScope();
但是,当Parallel.ForEach()从单个线程内部启动时,我不再能够访问Application1LoggingContext对象,也无法将ILoggingContext重新绑定到它。这是因为Parallel.ForEach()从基类运行,并且不知道它需要绑定到哪个Application LoggingContext。这是在每个应用程序内部完成的,在启动大20个线程时。
我想修改一个基类,一个旋转Parallel.ForEach()并确保在每个新创建的Parallel.ForEach线程内部,ILoggingContext仍然绑定到Application1LoggingContext - 一般来说,所以我可以执行以下操作:
var ctx = Kernel.Get<ILoggingContext>();
答案 0 :(得分:1)
看起来我已经弄明白了。这是在Parallel.Foreach中重新绑定绑定的通用方法。根据绑定的复杂性/数量,这可能会或可能不适合您开箱即用
var logBinding = Kernel.GetBindings(typeof(ILoggingContext)).FirstOrDefault();
Parallel.ForEach(items, n =>
{
if (Kernel.GetBindings(typeof(ILoggingContext)).Count() == 0 && logBinding != null)
Kernel.AddBinding(logBinding);
//do stuff
}
});
答案 1 :(得分:0)
你能在闭包中捕获ILoggingContext以传递给Parallel.ForEach()迭代吗?
启动Parallel.ForEach()的基类方法(StartUpBase.Start()
)可以从父线程上的上下文感知派生类型(StartUpApplication1
)调用。派生类型可以从Ninject内核中获取要传递给子节点的ILoggingContext
,并将其传递给基类方法,然后通过闭包将其传递给并行迭代:例如:
abstract class StartUpBase
{
public abstract void Start();
protected void StartApplication<T>(ILoggingContext ctx, IEnumerable<T> enumerableWork)
{
Parallel.ForEach(enumerableWork, iter =>
{
// this code can refer to ctx e.g.
ctx.Log(message);
});
}
}
internal class StartupApplication1<T> : StartUpBase
{
// setup of this is elsewhere...
private IEnumerable<T> _enumerableWork;
public override void Start()
{
ILoggingContext ctx = Kernel.Bind<ILoggingContext>()
.To<Application1LoggingContext>().InThreadScope();
StartApplication(ctx, _enumerableWork);
}
}