简体   繁体   English

锁定语句似乎不起作用

[英]lock statement does not appear to be working

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 am calling it from multiple threads (calling the same instance), but an exception keeps being thrown on TableProperty.Single (Sequence contains no elements). 我从多个线程调用它(调用相同的实例),但TableProperty.Single始终引发异常(序列不包含任何元素)。 Upon debugging the code I saw that a situation is being created where the item is being deleted from the database after a different thread has checked the cache for its existence. 调试代码后,我看到正在创建一种情况,在另一个线程检查了高速缓存的存在之后,正在从数据库中删除该项目。 This should not be possible unless there are multiple threads inside the lock statement (The syncroot object is definitely the same instance across threads). 除非lock语句中有多个线程,否则这应该是不可能的(syncroot对象在线程之间肯定是相同的实例)。

Impossible? 不可能? I have proof: 我有证据: 不可能的情况

There are three threads inside the lock statement! lock语句中有三个线程! What gives? 是什么赋予了?

notes: 笔记:

  1. The MRE is set (not blocking). MRE已设置(不阻止)。
  2. This is not a situation where the exception gets thrown, it just shows multiple threads inside a lock section. 这不是抛出异常的情况,它仅显示锁部分中的多个线程。 Update : I changed the image to an intellitrace event of the exception. 更新 :我将图像更改为异常的intellitrace事件。 The old image is here 旧的图片在这里
  3. The syncroot object is not static, because I only want calls to the same instance syncronized. syncroot对象不是静态的,因为我只希望同步调用同一实例。

Update 更新资料

This is the declaration of the syncroot object: 这是syncroot对象的声明:

private object syncroot = new object();

And some other declarations: 还有其他一些声明:

private ManualResetEventSlim waitForContextMRE = new ManualResetEventSlim(true);
private DataContextType _dataContext;
private System.Data.Linq.Table<EntityType> _tableProperty;
//DataContextType and EntityType are generic type parameters

I cannot make the syncroot static because I have several instances of the class running and it is important that they don't block each other. 我无法使syncroot保持静态,因为我有几个正在运行的类实例,并且它们之间不能互相阻塞很重要。 But that doesn't really matter - making it static does not fix the problem. 但这并不重要-将其设置为静态并不能解决问题。

The ManualResetEvent (waitForContextMRE) is not there for synchronization - it's there to block database operations for a certain time after certain operations are performed (ie on startup). 不存在ManualResetEvent(waitForContextMRE)进行同步-在执行某些操作后(即在启动时),它会在一段时间内阻止数据库操作。 It is set most of the time. 大多数情况下设置。 Taking it out of the lock block also does not fix the problem. 从锁定块中取出它也不能解决问题。

The only explanation I have is that waitForContextMRE.Wait(); 我唯一的解释是waitForContextMRE.Wait(); calling this makes the thread do unblock syncroot! 调用此命令会使线程取消阻塞syncroot! And so other thread can enter lock section. 因此其他线程可以进入锁定部分。 Try to move waitForContextMRE.Wait(); 尝试移动waitForContextMRE.Wait(); before lock(...). 在锁定(...)之前。

I think that you are calling different objects. 我认为您正在调用不同的对象。 There is no indication on your screenshot that you are taking values from different threads. 屏幕快照上没有迹象表明您正在从不同线程获取值。 Also using non static syncroot is not a good idea because may result in cases like yours. 另外,使用非静态syncroot也不是一个好主意,因为可能会导致像您这样的情况。 Do you have really strong reason not to have it static? 您是否真的有理由不希望它保持静态?

我建议锁定TableProperty或DataContext

I have been debugging this problem for a while now and, although I have not resolved it, it is clear to me that the locks are working . 我已经调试了一段时间,尽管我没有解决问题,但我很清楚锁在起作用 I am guessing the problem is with the DataContext (which are known for being tricky in multithreaded situations). 我猜想问题出在DataContext(以在多线程情况下棘手而闻名)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM