I have this method:
public bool Remove(EntityKeyType key)
{
lock (syncroot)
{
waitForContextMRE.Wait();
if (!localCache.ContainsKey(key)) return false;
Expression<Func<EntityType, bool>> keyComparitorExpression = GenerateKeyComparitorExpression(key);
var itemToDelete = TableProperty.Single(keyComparitorExpression);
TableProperty.DeleteOnSubmit(itemToDelete);
DataContext.SubmitChanges();
EntityType itemToRemove = localCache[key];
itemToRemove.PropertyChanged -= item_PropertyChanged;
Debug.Assert(localCache.Remove(key));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, itemToRemove));
return true;
}
}
I call it from multiple threads (calling the same instance), but the exception is stored in TableProperty.Single (Sequence does not contain elements). After debugging the code, I saw that a situation was created when an element was deleted from the database after another thread checked the cache for its existence. This should not be possible if there are no multiple threads in the lock statement (the syncroot object is definitely the same instance for the threads).
impossible? I have proof:

There are three threads in the lock statement! What gives?
notes:
- MRE is installed (not blocked).
- , , . . intellitrace .
- syncroot , , .
syncroot:
private object syncroot = new object();
:
private ManualResetEventSlim waitForContextMRE = new ManualResetEventSlim(true);
private DataContextType _dataContext;
private System.Data.Linq.Table<EntityType> _tableProperty;
syncroot static, , , . , .
ManualResetEvent (waitForContextMRE) - (.. ). . .