3
votes

I'm pushing a lot of data into CRM at times, like bulk updates. It is done in a workflow (CodeActivity) class, with its Execute() method. I can use the argument (the context) passed to that method to get the ServiceFactory, and then in turn create the IOrganizationService.

I then iterate a list of objects to update, change properties, and call service.Update(myObj). So far so good.

Now, to speed things up, I thought I'd run 2-4 threads that do the update in parallel.

Question 1 Should I reuse the service I just created, or create a new one, if I run two or more threads? I.e. create one service per thread, or share it?

I'm basically doing Parallel.Invoke(action1, action2, action3); where each action needs a service instance to call service.Update(myObj);

Question 2 If calling serviceFactory.CreateOrganizationService(context.UserId), will it actually create a new service, or return an existing one?

I have everything else nailed down, and it is working just fine, but wanted to get a recommendation/best practice for when multithreading within a workflow's Execute() method.

2

2 Answers

1
votes

I would be a little surprised if mulit-threading your application would actually improves performance (But if you can post data that says otherwise, I would love to see it)

Question 1:

The CrmOrganizationService that is used on the client side is not thread safe, I doubt the server version that implements the IOrganizationService is thread safe as well.

Question 2:

I am not aware of Microsoft specifying one way or the other, so that would lead me to believe that whatever the answer is, you can't count on it. The interface doesn't define the answer, so it could potentially be changed with the next update. With that being said, I would just test it yourself:

if(Object.ReferenceEquals(serviceFactory.CreateOrganizationService(context.UserId), serviceFactory.CreateOrganizationService(context.UserId)){
    throw new Exception("Returns the same IOrganizationService");
}

throw new Exception("Returns a new IOrganizationService");
1
votes

So, to summarize, it works just fine to run multiple threads in CRM, from within a workflow. Do this:

  1. Use the executionContext parameter passed to the Execute() method.
  2. Create an IOrganizationService like this:

IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>(); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

Now use that service for one thread/task. If you run many threads, create one service per thread.

The other issues I had was related to a specific CRM Addon.