1

when doing parallel/multithreading, if there are dependencies that are not thread safe, what kind of instance method can be used with autofac to get an instance per thread? from what I know, autofac is the kind of DI container for certain framework like asp.net/mvc but for the rest of the app type like windows service, it does not have any support. in my scenario, i am doing multithreading for a windows service that also hosting a web api service. what kind of registration can be used so that it will work for web api instanceperhttprequest and instanceperlifetimescope. two separate container?

EDIt:

using this parallel extension method here:

public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
    {
        return Task.WhenAll(
            from partition in Partitioner.Create(source).GetPartitions(dop)
            select Task.Run(async delegate
            {
                using (partition)
                {
                    while (partition.MoveNext())
                    {
                        await body(partition.Current);
                    }
                }
            }));
    }

so the body will be use to do the work. DI will need to be inside of the body func.

koo9
  • 409
  • 5
  • 15
  • Can you add an example of a consumer of this extension method? – Steven Dec 27 '14 at 21:05
  • see this thread http://stackoverflow.com/questions/14673728/run-async-method-8-times-in-parallel – koo9 Dec 30 '14 at 21:09
  • That's not what I meant. I like to see how you are using this in your case. So what services do you call. What are their names. I like to see the context. It's not about the (technical ) how, but about the (functional) what. Such example gives us context and allows us to tailor our answer to your context. The right answer often depends on the context. – Steven Dec 30 '14 at 22:29
  • giving it a little more thoughts. I guess it's not quite possible to implement this with autofac due to its scoping design nature. all instance it's resolve within a scope (not a good idea to use the root). since the multithreading start within a class aka from a method call therefore the scope will have to occur within the method as suggested [here](http://autofac.readthedocs.org/en/latest/lifetime/instance-scope.html#thread-scope) – koo9 Dec 31 '14 at 05:57

1 Answers1

1

It doesn't matter what kind of application you run; the pattern is always the same. You should resolve one object graph per request. In a web application, a request means a web request, in a windows service, a request is usually a timer pulse.

So in a windows service, each 'pulse' you start a new lifetime scope, and within this scope you resolve your root object and call it.

If however, you process items in parallel within a single request, you should see each processed item as a request of its own. So that means that on each thread you should start a new lifetime scope and resolve a sub object graph from that scope and execute that. Prevent passing services that are resolved from your container, from thread to thread. This scatters the knowledge of what is thread-safe, and what isn't throughout the application, instead of keeping that knowledge centralized in the startup path of your application where you compose your object graphs (the composition root).

Take a look at this article about working with dependency injection in multi-threaded applications. It's written for a different DI library, but you'll find most of the advice generically applicable to all DI libraries.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • When resolving the service in each thread, to ensure only one instance per thread, I end up using a service locator to resolve the service on demand but keep a registry of scopes within the locator. the scope is lookup by the thread id. that works fine. – koo9 Dec 24 '14 at 16:33
  • @koo9: nope, no service locator needs to be harmed when doing this. Put an abstraction around the code that processes stuff in parallel, and create an implementation of this in your composition root. This implementation can call back into the container, and since this is located inside your composition root, this is no form of service locator. – Steven Dec 24 '14 at 18:13
  • not too clear on your idea, maybe some code snippet would help. :) – koo9 Dec 24 '14 at 21:57
  • @koo9: [This earlier answer of mine](https://stackoverflow.com/questions/13982600/) describes this a bit more. I like to show you some examples, but to be able to do this, I need to know more about your design. If you are interested in some examples, please update your question with the appropriate pieces of code. – Steven Dec 24 '14 at 23:13
  • basically the windows service will run a timer (since MySQL server does not support sqldependency out of the box ) to monitor a queue table to process work. The work could be done in parallel. In my case it's generating reports with crystal report. I have this reportmanager class that is called by the reportqueuewatcher class. In in the reportmanager class, it retrieved the list of queue items and run them in parallel. within each report queue item, each report might have parallel tasks to generate part of a report then at the end itextsharp will concatenate the parts into one pdf. – koo9 Dec 24 '14 at 23:44
  • just read the doc on [multithreading Di](https://simpleinjector.readthedocs.org/en/latest/howto.html#multi-threaded-applications) for simpleinjector, excellent use of func, which pass code as argument. not user if autofac support register decorator out of the box. – koo9 Dec 25 '14 at 00:12
  • @koo9: Autofac has support for decorators, but things like decoratee-factories and conditional decoration are not supported OOTB unfortunately. AFAIK Simple Injector is the only container who supports this. – Steven Dec 25 '14 at 09:30