LINQ Changeset多线程

时间:2010-05-25 20:07:00

标签: c# multithreading linq-to-sql

我正在使用LINQ to SQL,在我提交一些更改后,我想生成一个线程,查看所有更改并根据需要更新我们的lucene索引。我的代码看起来很模糊:

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

有时虽然我得到一个InvalidOperationException,我认为是因为context.GetChangeSet()不是线程安全的,所以如果在一个线程中修改了更改集而另一个线程通过它进行枚举,则会出现问题。

是否存在GetChangeSet()的“线程安全”版本?或者某种方式我可以做ChangeSet.clone()或其他什么?

2 个答案:

答案 0 :(得分:2)

DataContext的实例成员不是线程安全的

为了避免竞争条件,您应该从同一个线程调用DataContext.GetChangeSet方法,该线程使DataContext实例跟踪修改。例如:

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); 
    }
}

这假设从单个线程在CustomerDao类的给定实例上调用Insert和Delete方法。

答案 1 :(得分:0)

我只需要从每个对象中提取少量数据,因此我最终只是提取文本,将其放入一个新对象,然后关闭该新对象。这让我在其他任何地方处理锁定时省去了很多麻烦,但我认为Enrico的答案可能是“真正的”,所以留下他的标记为解决方案。