Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject, Parallel.ForEach and InThreadScope()

I would appreciate suggestions as to how to implement the following with Ninject:

I have a multi-threaded application. It runs approximately 20 very independent threads concurrently. Upon the application startup, I bind an interface to an object via Ninject by using InThreadScope() and all works well. Each thread receives object specific to its thread (constructor of each object instantiates a number of thread-specific flags).

Most of the work that each thread does, is waiting for data-storage to finish process. So, in order to optimize the threads even further, we've implemented Parallel.ForEach logic inside the main 20 threads. I would like for threads generated by Paralell.ForEach to get the same binding as their parent thread. However, I cannot simply re-bind the interface to appropriate object inside the Parallel.ForEach, I simply do not know what the bound object is - inside Paralell.ForEach I can only work with the interface.

What's the proper way to retrieve bindings from the Kernel at runtime, before Paralell.ForEach starts and re-bind them generically inside the loop?

Edit: attempting to include detailed logic/pseudocode:

Each thread once started does something like this:

Kernel.Bind<ILoggingContext>().To<Application1LoggingContext>().InThreadScope();

However, when Parallel.ForEach() kicks in, from inside the individual threads, I no longer have access to Application1LoggingContext object and cannot rebind the ILoggingContext to it. This is because the Parallel.ForEach() is running from a base class and knows not what Application LoggingContext it needs to be bound to. That is done inside each application, upon starting of the big 20 threads.

I'd like to modify the base class, the one that spins up Parallel.ForEach() and ensure inside of each newly created by Parallel.ForEach thread, that ILoggingContext is still bound to Application1LoggingContext - generically, so that I can perform the following:

var ctx = Kernel.Get<ILoggingContext>();
like image 395
Igorek Avatar asked Nov 14 '22 08:11

Igorek


1 Answers

Looks like I've figured this out. Here is a generic way to rebind a binding inside Parallel.Foreach. Depending on the complexity/number of bindings, this may or may not work for you out of the box

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
                                }
                            });
like image 138
Igorek Avatar answered Nov 16 '22 03:11

Igorek