1

My application retrieves Subject info from a web service, and inserts it into the local database. While creating the Subject, an associated Job is also created. First the local repository is checked to see if that Job exists; if not, another web service request is made for the Job, and then that is saved to the local repository as well.

The problem is that occasionally duplicate Jobs are created because 2 users are logging in at the same time with 2 Subjects that share the same Job. For the first one, the Job doesn't exist, so it is retrieved from the service and created; for the second one, the job doesn't exist, but it is created by the first request before the second request's web service call returns. So then the duplicate is created.

I have tried checking the local repository again, after the web service returns, but that is not sufficient to catch this all the time; the timing is such that it seems to happen simultaneously, so I can't catch it.

My idea is to somehow lock the second (and subsequent) user(s) out of the method until the first request returns, but I'm not sure if a) that's a good idea, and b) if it is, how to do that? I was thinking of creating a temporary flag in the database and blocking until it is cleared, but is there a better way? Can I decorate the C# method in some way so that only one session can access it at a time?

Advice, anyone? Thank you!

1 Answers1

3

You have a pretty clear race condition, one solution is to use a locking object to control access to your database reads / writes

private static object syncObject = new object()

...
lock(syncObject)
{
    // exclusive DB access
}

A lock will allow only one thread at a time to gain exclusive access which effectively negates any race condition. When a second thread hits the lock it's blocked until the the first thread has finished & released the lock (the lock is released automatically once you leave the critical section).

For more info, you can read about how the lock statement works.

Community
  • 1
  • 1
James
  • 80,725
  • 18
  • 167
  • 237