Blocking statement does not work

I have this method:

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

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: Impossible situation

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;
//DataContextType and EntityType are generic type parameters

syncroot static, , , . , .

ManualResetEvent (waitForContextMRE) - (.. ). . .

+5
4

, , , . , DataContext (, , ).

0

, , waitForContextMRE.Wait(); ! . waitForContextMRE.Wait(); (...).

+3

I think you are calling different objects. There is no indication in the screenshot that you are accepting values ​​from different threads. Also, using non-static synchronism is not a good idea, as it can lead to cases like yours. Do you have a really strong reason not static?

+3
source

I suggest lock TableProperty or DataContext

0
source

All Articles