I'm working on a .NET application where I off-load my DB work (save operations) to a separate thread (inspired by how NodeJS handles IO operations). A save operation comes down to this (using Entity Framework):

public void Save(Customer customer)
    Task.Factory.StartNew(() =>
        using (var entities = new MyEntities())
            var persistedCustomer 
                = entities.Customers.FirstOrDefault(x => x.Number == customer.Number);

            if (persistedCustomer == null)
                persistedCustomer = new DBCustomer();
                // set properties
                // set properties


So, in essence:

  • check if entity already exists in the DB
  • if not, create a new one
  • if it does already exist, update the existing one

Where this sometimes breaks down is when two calls to the Save method are made at the same time. Both threads see the entity doesn't exist yet and they want to do an insert. A standard race condition.

How would you go about fixing this? Any experience with this?

I could implement a retry mechanism, but was wondering if there are other options. A simple retry could of course overwrite certain properties that the previous save had updated.

  • One problem with your example is that this code assumes Customer (the one passed into your Save function) is a thread safe object. Either you need to make Customer immutable, or you need to use some other kind of locking or memory barrier. I suggest creating an immutable copy. – Scott Whitlock Mar 17 '15 at 15:46
  • 4
    ...since Entities are by definition mutable objects, you should never ever pass an Entity across a thread boundary, which I'm afraid is what you're doing here. – Scott Whitlock Mar 17 '15 at 15:53
  • "inspired by how NodeJS handles IO operations" that's not how node works. – Alex Wiese Dec 17 '19 at 3:35
  • @AlexWiese I'm open to constructive criticism (see meta.stackexchange.com/questions/19756/how-do-comments-work) but just saying something is wrong doesn't help me or anyone else here learn how (in this case) Node.js does work. That being said, it's been a while. I guess what you're trying to say (correctly) is that my code does a fire-and-forget on another thread, while Node.js will allow other request when waiting for IO to finish, but it won't continue the execution of the current piece of code. – Peter Dec 18 '19 at 7:53
  • Sorry yes I should have expanded. It does naturally async IO rather than using multiple threads . – Alex Wiese Dec 18 '19 at 11:48

Problems like this are often solved with queues.

If you are saving same customer, you insert it into one ConcurrentQueue<T>. Then there is one thread that reads the queue sequentially and does the update on each item read. Only place where the synchronization between threads occurs is in insertion to the queue and that can be done both fast and without risk of deadlocks.

  • I use producer consumer queues quite a bit in my multithreaded code. System.Collections.Concurrent is a wonderful namespace added in to the framework. – RubberChickenLeader Mar 17 '15 at 20:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.