views:

183

answers:

6

Have you got some good advices to use EF in a multithread program ?

I have 2 layers :

  • a EF layer to read/write into my database
  • a multithread service which uses my entities (read/write) and makes some computations (I use Task Parallel Library in the framework)

How can I synchronize my object contexts in each thread ? Do you know a good pattern to make it work ?

A: 

I think Craig might be right about your application no needing to have threads.. but you might look for the uses of ConcurrencyCheck in your models to make sure you don't "override" your changes

Shady M. Najib
A: 

I don't know how much of your application is actually number crunching. If speed is the motivation for using multi-threading then it might pay off to take a step back and gather data about where the bottle next is.

In a lot of cases I have found that the limiting factor in applications using a database server is the speed of the I/O system for your storage. For example the speed of the hard drive disk(s) and their configuration can have a huge impact. A single hard drive disk with 7,200 RPM can handle about 60 transactions per second (ball park figure depending on many factors).

So my suggestion would be to first measure and find out where the bottle next is. Chances are you don't even need threads. That would make the code substantially easier to maintain and the quality is much higher in all likelihood.

John
+1  A: 

Good advice is - just don't :-) EF barely manages to survive one thread - the nature of the beast.

If you absolutely have to use it, make the lightest DTO-s, close OC as soon as you have the data, repack data, spawn your threads just to do calculations and nothing else, wait till they are done, then create another OC and dump data back into DB, reconcile it etc.

If another "main" thread (the one that spawns N calculation threads via TPL) needs to know when some ther thread is done fire event, just set a flag in the other thread and then let it's code check the flag in it's loop and react by creating new OC and then reconciling data if it has to.

If your situation is more simple you can adapt this - the key is that you can only set a flag and let another thread react when it's ready. That means that it's in a stable state, has finished a round of whatever it was doing and can do things without risking race conditions. Reset the flag (an int) with interchaged operations and keep some timing data to make sure that your threads don't react again within some time T - otherwire they can spend their lifetime just querying DB.

ZXX
A: 

"How can I synchronize my object contexts in each thread ?" This is going to be tough. First of all SP or the DB queries can have parallel execution plan. So if you also have parallelism on object context you have to manually make sure that you have sufficient isolation but just enough that you dont hold lock too long that you cause deadlocks.

So I would say dont need to do it .

But that might not be the answer you want. So Can you explain a bit more what you want to achieve using this mutithreading. Is it more compute bound or IO bound. If it is IO bound long running ops then look at APM by Jeff Richter.

Ashwani Roy
A: 

I think your question is more about synchronization between threads and EF is irrelevvant here. If I understand correctly you want to notify threads from one group when the main thread performed some operation - in this case "SaveChanges()" operation. The threads here are like client-server applications, where one thread is a server and other threads are clients and you want client-threads to react on server activity.

As someone noticed you probably do not need threads, but let's leave it as it is.

There is no fear of dead locks as long as you are going to use separate OC per thread.

I also assume that your client threads are long-running thread in some kind of loop. If you want your code to be executed on client thread you can't use C# events.

class ClientThread {
public bool SomethingHasChanged;

  public MainLoop()
  {
    Loop {
      if (SomethingHasChanged)
      { 
        refresh();
        SomethingHasChanged = false;
      }

      // your business logic here


    } // End Loop
  }
}

Now the question is how you will set the flag in all your client-threads? You could keep references to client threads in your main thread and loop through them and set all flags to true.

Michal Jankowski
A: 

Back when I used EF, I simply had one ObjectContext, to which I synchronized all access.

This isn't ideal. Your database layer would effectively be singlethreaded. But, it did keep it thread-safe in a multithreaded environment. In my case, the heavy computation was not in the database code at all - this was a game server, so game logic was of course the primary resource hog. So, I didn't have any particular need for a multithreaded DB layer.

Zor