我有这个方法:
public bool Remove(EntityKeyType key)
{
lock (syncroot)
{
//wait if we need to
waitForContextMRE.Wait();
//if the item is not local, assume it is not remote.
if (!localCache.ContainsKey(key)) return false;
//build an expression tree
Expression<Func<EntityType, bool>> keyComparitorExpression = GenerateKeyComparitorExpression(key);
var itemToDelete = TableProperty.Single(keyComparitorExpression);
//delete from db
TableProperty.DeleteOnSubmit(itemToDelete);
DataContext.SubmitChanges();
//get the removed item for OnCollectionChanged
EntityType itemToRemove = localCache[key];
itemToRemove.PropertyChanged -= item_PropertyChanged;
//remove from the list
Debug.Assert(localCache.Remove(key));
//call the notification
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, itemToRemove));
return true;
}
}
我从多个线程中调用它(调用同一实例),但是TableProperty.Single(序列不包含任何元素)会抛出异常。通过调试代码,我发现在一个不同的线程检查缓存中是否存在该项后,该项正在从数据库中删除。除非在锁定语句内有多个线程(同步对象跨线程绝对是相同的实例),否则不可能发生这种情况。
不可能?我有证据:
锁定语句中有三个线程!怎么回事?
注意:
- MRE已设置(未阻止)。
- 这不是引发异常的情况,只是显示锁定部分内的多个线程。更新:我将图像更改为intellitrace异常事件。旧图像在此处。
- 同步对象不是静态的,因为我只想要对同一实例的调用进行同步。
更新
这是同步对象的声明:
private object syncroot = new object();
还有一些其他的声明:
private ManualResetEventSlim waitForContextMRE = new ManualResetEventSlim(true);
private DataContextType _dataContext;
private System.Data.Linq.Table<EntityType> _tableProperty;
//DataContextType and EntityType are generic type parameters
我无法将syncroot设置为静态,因为我有多个类实例在运行,重要的是它们不会互相阻塞。但这并不重要-使它静态并不能解决问题。ManualResetEvent(waitForContextMRE)不用于同步-它用于在执行某些操作后(例如启动时)阻止数据库操作一段时间。它大部分时间都被设置。将其从锁定块中删除也无法解决问题。
syncroot
吗? B: 对象上下文会持续多久? C: 你确定它们是同一个实例吗?从暂停状态很难判断... - Marc Gravell