Я использую LINQ для SQL и после того, как я отправляю некоторые изменения, я хочу породить поток, который просматривает все изменения и обновляет наш индекс lucene по мере необходимости. Мой код смотрит неопределенно как:
(new Thread(() => { UpdateIndex(context.GetChangeSet()); }).Start();
Иногда, хотя я получаю InvalidOperationException, который я думаю, то, потому что контекст. GetChangeSet () не ориентирован на многопотоковое исполнение, и поэтому если массив изменений изменяется в одном потоке, в то время как другой поток перечисляет через него, проблемы возникают.
Существует ли "ориентированная на многопотоковое исполнение" версия GetChangeSet ()? Или некоторый путь я могу сделать ChangeSet.clone () или что-то?
Члены экземпляра класса 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);
}
}
Здесь предполагается, что методы Insert и Delete вызываются на данном экземпляре класса CustomerDao из одного потока.
Мне нужно было извлечь только небольшое количество данных из каждого объекта, так что в итоге я просто извлек текст, поместил его в новый объект, а затем отправил этот новый объект. Это избавило меня от необходимости возиться с блокировкой в других местах, но я думаю, что ответ Энрико, вероятно, является "настоящим" ответом, поэтому оставляю его как решение.