Search code examples
mef

Shared instance only created once for many contaieners? I must be blind


I am using MEF in a framework to compose worker threads "available processors" dynamically at runtime.

There is a queue of items to process, and a large number of worker threads (16) get instantiated. There is a ommon CompositionContainer that is used by the class managing the queue, then every worker creates it's own container:

       using (CompositionContainer container = new CompositionContainer(CompositionContainer)) {
            container.ComposeExportedValue<CompositionContainer> (container);
            using (Processor.ProcessorSession session = container.GetExport<Processor.ProcessorSession>().Value) {
                Data data;
                while (_DataQueue.Dequeue(out data)) {
                    session.ProcessData(data);
                }
            }
        }

My problem is that in the Processor.ProcessorSession a DataManager is instantiated by MEF as a shared object - which is OK, I want it to be unique within the "work context". Sadly, this results in ONE DataManager existing, not one per sub-container. This, incidentally, results in ..... a lot of chao (a.k.a. bugging out).

Where is the error? Do the sub-containers just delegate up to the parent automatically? How do I stop this?

There is only one catalog defined at the top, and for this particular scenario I would really like to avoid dealing with custom catalogs at this level.

Suggested readings? Suggested solutions?

Wanted behavior: * There is no DataManager instntiated in the base composition container. * I want it to be shared within the sub-containe (the one created in the example code) * BUT: every worker thread has it's own subcontainer and as such the shared "context" should be the sub-container, not the parent one (i.e. one DataManager created per thread, within the ProcessorSession).


Solution

  • You need to identify which parts should be shared per work-context, and which ones should be shared globally. You should put them in separate catalogs, and the parent container should use the catalog of parts which should be shared globally, while the child container should use the the catalog with parts that should be unique within the work-context.

    If there are no parts which need to be shared globally, then you don't need a parent-child container relationship at all. Just create a separate CompositionContainer for each worker. I'd recommend creating the catalog only once, as this will help with performance.

    If you do need to split your parts into two different catalogs, the FilteredCatalog in the latest MEF preview may help you. Also, right now we are working on some more functionality along these lines (so that hopefully you wouldn't have to manage splitting the catalog yourself). When we release a new preview with that functionality we'll be looking for feedback, so watch the MEF codeplex site, as well as some of the blogs for the MEF team members: