views:

71

answers:

2

I'm using LINQ to SQL and after I submit some changes I want to spawn a thread which looks through all the changes and updates our lucene index as necessary. My code looks vaguely like:

(new Thread(() => { UpdateIndex(context.GetChangeSet()); }).Start();

Sometimes though I get an InvalidOperationException, which I think is because context.GetChangeSet() is not thread-safe, and so if the change set is modified in one thread while another thread is enumerating through it, problems arise.

Is there a "thread-safe" version of GetChangeSet()? Or some way I can do ChangeSet.clone() or something?

+2  A: 

Instance members of the DataContext class are not thread-safe.

In order to avoid race conditions you should invoke the DataContext.GetChangeSet method from the same thread that makes the modifications tracked by the DataContext instance. For example:

public class CustomerDao : IDisposable
{
    private DataContext context;

    public CustomerDao()
    {
        this.context = new DataContext("SomeConnectionString");
    }

    public void Insert(Customer instance)
    {
        this.context.Customers.InsertOnSubmit(instance);
        this.StartUpdateIndex();
        this.context.SubmitChanges();
    }

    public void Delete(Customer instance)
    {
        this.context.Customers.DeleteOnSubmit(instance);
        this.StartUpdateIndex();
        this.context.SubmitChanges();
    }

    public void Dispose()
    {
        if (this.context != null)
        {
            this.context.Dispose();
        }         
    }

    private void StartUpdateIndex()
    {
        ChangeSet changes = this.context.GetChangeSet();
        ThreadPool.QueueUserWorkItem(
            state => this.UpdateIndex((ChangeSet)state), changes); 
    }
}

This assumes that the Insert and Delete methods are being called on a given instance of the CustomerDao class from a single thread.

Enrico Campidoglio
The only time I want multiple threads is just for the StartUpdateIndex() thing; is there any way that I can just copy the change set into a thread-safe structure? I don't need my insert, delete etc. methods to be thread-safe, so I'd like to avoid having to write a bunch of locking code.
Xodarap
I see what you mean. I updated my answer and removed all locking code on the assumption that only the UpdateIndex method will be run on different threads.
Enrico Campidoglio
A: 

I only needed to extract a small amount of data from each object, so for I ended up just extracting the text, putting it into a new object, then sending that new object off. This saved me a lot of trouble from having to deal with locking everywhere else, but I think Enrico's answer is probably the "real" one, so leaving his marked as the solution.

Xodarap