प्रकट नहीं होता है मैं इस विधि है:ताला बयान काम करने
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 सेट किया गया है (नहीं अवरुद्ध)।
- यह ऐसी स्थिति नहीं है जहां अपवाद फेंक दिया जाता है, यह केवल लॉक सेक्शन के अंदर कई धागे दिखाता है। अद्यतन: मैंने छवि को अपवाद के इंटेलिट्रेस ईवेंट में बदल दिया। पुरानी छवि here
- सिंक्रूट ऑब्जेक्ट स्थिर नहीं है, क्योंकि मुझे केवल सिंक्रनाइज़ किए गए एक ही उदाहरण पर कॉल चाहिए।
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 स्थिर है क्योंकि मैं नहीं कर सकते हैं
अद्यतन
यह syncroot वस्तु की घोषणा है कक्षा के कई उदाहरण चल रहे हैं और यह महत्वपूर्ण है कि वे ब्लॉक न करें एक दूसरे के। लेकिन इससे कोई फर्क नहीं पड़ता - इसे स्थैतिक बनाना समस्या को ठीक नहीं करता है।
ManualResetEvent (waitForContextMRE) तुल्यकालन के लिए वहाँ नहीं है - यह एक निश्चित समय के लिए डेटाबेस कार्यों को ब्लॉक करने के बाद निश्चित संचालनों के प्रदर्शन कर रहे हैं वहाँ (अर्थात स्टार्टअप पर)। यह ज्यादातर समय सेट है। इसे लॉक ब्लॉक से बाहर लेना भी समस्या को ठीक नहीं करता है।
ए: क्या हम देख सकते हैं कि आप 'सिंक्रोट' कहां शुरू कर रहे हैं, और बी: वस्तु-संदर्भ कितने समय तक लात मार रहा है? सी: क्या आप वाकई एक ही उदाहरण हैं? एक रोके गए राज्य से बताना मुश्किल है ... –
मैं सिस्टम.डिग्नोस्टिक्स.डिबग.राइटलाइन के साथ ट्रेस संदेश जोड़ने का सुझाव दूंगा। शुरुआत में और लॉक ब्लॉक के अंत में थ्रेड आईडी और सिंक्रूट हैशकोड लिखें। फिर आप आउटपुट विंडो में आसानी से देख सकते हैं यदि दो धागे एक ही सिंक्रूट के साथ ओवरलैप होते हैं, जो निश्चित रूप से नहीं होना चाहिए। –
सिंक्रूट स्थिर बनाने में क्या नुकसान है? –