2012-01-26 17 views
17

पर अपवाद मुझे इस अपवाद के बारे में अलग-अलग लेख मिल गए हैं, लेकिन उनमें से कोई भी मेरा मामला नहीं था। यहाँ स्रोत कोड है:ऑब्जेक्ट सिंक्रनाइज़ेशन विधि को कोड के एक सिंक्रनाइज़ किए गए ब्लॉक से बुलाया गया था। Mutex.Release()

class Program 
{ 

    private static Mutex mutex; 
    private static bool mutexIsLocked = false; 
    static void Main(string[] args) 
    { 

     ICrmService crmService = 
      new ArmenianSoftware.Crm.Common.CrmServiceWrapper(GetCrmService("Armsoft", "crmserver")); 
     //Lock mutex for concurrent access to workflow 
     mutex = new Mutex(true, "ArmenianSoftware.Crm.Common.FilterCtiCallLogActivity"); 
     mutexIsLocked = true; 

     //Create object for updating filtered cti call log 
     ArmenianSoftware.Crm.Common.FilterCtiCallLog filterCtiCallLog = 
      new ArmenianSoftware.Crm.Common.FilterCtiCallLog(crmService); 
     //Bind events 
     filterCtiCallLog.CtiCallsRetrieved += new EventHandler<ArmenianSoftware.Crm.Common.CtiCallsRetrievedEventArgs>(filterCtiCallLog_CtiCallsRetrieved); 

     //Execute filter 
     try 
     { 
      filterCtiCallLog.CreateFilteredCtiCallLogSync(); 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
     finally 
     { 
      if (mutexIsLocked) 
      { 
       mutexIsLocked = false; 
       mutex.ReleaseMutex(); 
      } 
     } 
    } 

    static void filterCtiCallLog_CtiCallsRetrieved(object sender, 
     ArmenianSoftware.Crm.Common.CtiCallsRetrievedEventArgs e) 
    { 
     tryasasas 
     { 
      if (mutexIsLocked) 
      { 
       mutexIsLocked = false; 
       mutex.ReleaseMutex(); 
      } 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
    } 
} 

filterCtiCallLog.CreateFilteredCtiCallLogSync(); समारोह सर्वर के लिए अनुरोध निष्पादित करता है, और कुछ घटनाओं, CtiCallsRetrieve घटना है, जिनमें से एक को जन्म देती है। और जब इस घटना को निकाल दिया जाता है तो मुझे म्यूटेक्स को छोड़ना होगा। लेकिन mutex को कॉल करने पर। कृपया() फ़ंक्शन अपवाद फेंक दिया गया है। CreateFilteredCtiCallLogSync तुल्यकालिक रूप से काम करता है। समस्या क्या है?

उत्तर

33

इसके आसपास एक बूल रखना इंगित करता है कि म्यूटेक्स का स्वामित्व एक गंभीर गलती है। आप बूल थ्रेड-सुरक्षित नहीं बना रहे हैं। आप इस अचार में आ गए क्योंकि आप गलत सिंक्रनाइज़ेशन ऑब्जेक्ट का उपयोग कर रहे हैं। एक म्यूटेक्स में थ्रेड-एफ़िनिटी है, म्यूटेक्स का मालिक थ्रेड है। जिस धागे को अधिग्रहित किया गया वह भी रिलीजम्यूटेक्स() कहलाता है। यही कारण है कि आपका कोड बम।

आपको सभी संभावनाओं में ईवेंट की आवश्यकता है, ऑटोरसेट इवेंट का उपयोग करें। इसे मुख्य थ्रेड में बनाएं, कार्यकर्ता में प्रतीक्षा करें() को मुख्य थ्रेड में प्रतीक्षा करें() कार्यकर्ता को अपना काम पूरा करने के लिए प्रतीक्षा करें। और बाद में इसका निपटान करें। यह भी ध्यान रखें कि नौकरी करने के लिए धागे का उपयोग करना और अपना मुख्य धागा पूरा होने के लिए प्रतीक्षा करना उत्पादक नहीं है। आपके पास मुख्य धागा भी काम कर सकता है।

यदि आप वास्तव में ऐसा ऑब्जेक्ट तक पहुंचने के लिए ऐसा कर रहे हैं जो थ्रेड-सुरक्षित नहीं है (यह स्पष्ट नहीं है) तो लॉक कथन का उपयोग करें।

+0

आप सही हैं - मुझे याद आया कि कॉलबैक सेट करने वाला धागा मुख्य धागा है :( –

+0

ऑटोरेटेवेंट बहुत अच्छा है! धन्यवाद हंस। –

2

मेरे पास केवल एक या दो बार था, और हर मामले में यह एक म्यूटेक्स जारी करने की कोशिश कर रहा था, जिसका मेरा स्वामित्व नहीं था।

क्या आप सुनिश्चित हैं कि म्यूटेक्स पर उसी धागे पर ईवेंट उठाए गए हैं? यद्यपि आप उल्लेख करते हैं कि filterCtiCallLog.CreateFilteredCtiCallLogSync() एक अवरुद्ध कॉल है, शायद यह कार्यकर्ता धागे की संख्या पैदा करता है जो घटना को बढ़ाता है?

2

कर्नेल सिन्क्रो वस्तु राज्य की निगरानी के लिए सिर्फ काम नहीं करेगा प्रयास करने के लिए एक ध्वज का उपयोग करना - उन सिन्क्रो कॉल का उपयोग करने का मुद्दा यह है कि वे किसी भी स्पष्ट की जाँच के बिना सही ढंग से काम करता है। ध्वज सेट करने से केवल अड़चन समस्याएं पैदा होंगी क्योंकि ध्वज को जांचने और उस पर कार्य करने के बीच बाधाओं के कारण ध्वज को गलत तरीके से बदला जा सकता है।

एक म्यूटेक्स केवल इसे प्राप्त किए गए खतरे से मुक्त किया जा सकता है। यदि आप कॉलबैक को एक अलग थ्रेड द्वारा बुलाया जाता है, (CreateFilteredCtiCallLogSync() या कर्नेल थ्रेड पूल बनाने के लिए एक आंतरिक), रिलीज़ विफल हो जाएगा।

यह बिल्कुल स्पष्ट नहीं है कि आप क्या करने का प्रयास कर रहे हैं। संभवतः, आप CreateFilteredCtiCallLogSync() और कॉलबैक झंडे तक पहुंच को क्रमबद्ध करना चाहते हैं कि उदाहरण पुन: उपयोग के लिए उपलब्ध है? यदि ऐसा है, तो आप इसके बजाय एक सेमफोर का उपयोग कर सकते हैं - init। यह एक इकाई के लिए, शुरुआत में इसके लिए प्रतीक्षा करें और इसे कॉलबैक में छोड़ दें।

वहाँ कुछ मुद्दे जहां कभी कभी कॉलबैक नहीं बुलाया जाता है, और इसलिए ट्राई/अंत में/रिलीज है? यदि ऐसा है तो कॉलबैक असुरक्षित है और सेटअप थ्रेड फ़ंक्शन छोड़ने के बाद किसी अन्य थ्रेड द्वारा कॉल किया जा सकता है, तो इस तरह से थोड़ा सा लगता है।

5

मुझे समस्या मिली है। filterCtiCallLog वर्ग के बारे में सबसे पहले कई चीजें। मैंने इसे एसिंक्रोनस और सिंक्रोनस दोनों को काम करने के लिए डिज़ाइन किया है। पहले के लिए मैंने एसिंक्रोनस निष्पादन के लिए कोड लिखा है। मैं काम कर राज्य रिपोर्ट करने के लिए, माता पिता के लिए बच्चे कार्यकर्ता धागे से घटनाओं को गति प्रदान करने के लिए एक रास्ता की जरूरत है। इसके लिए मैंने AsyncOperation वर्ग और इसकी पोस्ट विधि का उपयोग किया है। यहाँ CtiCallsRetrieved ईवेंट सक्रिय करने के लिए कोड हिस्सा है।

public class FilterCtiCallLog 
{ 
    private int RequestCount = 0; 
    private AsyncOperation createCallsAsync = null; 
    private SendOrPostCallback ctiCallsRetrievedPost; 
    public void CreateFilteredCtiCallLogSync() 
    { 
     createCallsAsync = AsyncOperationManager.CreateOperation(null); 
     ctiCallsRetrievedPost = new SendOrPostCallback(CtiCallsRetrievedPost); 
     CreateFilteredCtiCallLog(); 
    } 

    private void CreateFilteredCtiCallLog() 
    { 
     int count=0; 
     //do the job 
     //............ 
     //........... 
     //Raise the event 
     createCallsAsync.Post(CtiCallsRetrievedPost, new CtiCallsRetrievedEventArgs(count)); 
     //........... 
     //........... 
    } 

    public event EventHandler<CtiCallsRetrievedEventArgs> CtiCallsRetrieved; 

    private void CtiCallsRetrievedPost(object state) 
    { 
     CtiCallsRetrievedEventArgs args = state as CtiCallsRetrievedEventArgs; 
     if (CtiCallsRetrieved != null) 
      CtiCallsRetrieved(this, args); 
    } 
} 

जैसा कि आप देख सकते हैं कि कोड सिंक्रनाइज़ेशन निष्पादित कर रहा है। यहां समस्या AsyncOperation.Post() विधि में है। मैंने माना कि अगर इसे मुख्य धागे में बुलाया जाता है तो यह घटना को ट्रिगर करने के रूप में कार्य करेगा, इसे मूल धागे पर पोस्ट नहीं करेगा। हालांकि यह मामला नहीं था। मुझे नहीं पता कि यह कैसे काम कर रहा है, लेकिन मैंने कोड बदल दिया है, यह जांचने के लिए कि CreateFilteredCtiCallLog को सिंक या एसिंक कहा जाता है या नहीं। और यदि यह एसिंक कॉल है तो मैंने AsyncOperation.Post विधि का उपयोग किया, यदि नहीं, तो मैंने EventHandler को ट्रिगर किया है यदि यह null नहीं है। यहां सही कोड

public class FilterCtiCallLog 
{ 
    private int RequestCount = 0; 
    private AsyncOperation createCallsAsync = null; 
    private SendOrPostCallback ctiCallsRetrievedPost; 
    public void CreateFilteredCtiCallLogSync() 
    { 
     createCallsAsync = AsyncOperationManager.CreateOperation(null); 
     ctiCallsRetrievedPost = new SendOrPostCallback(CtiCallsRetrievedPost); 
     CreateFilteredCtiCallLog(false); 
    } 

    private void CreateFilteredCtiCallLog(bool isAsync) 
    { 
     int count=0; 
     //do the job 
     //............ 
     //........... 
     //Raise the event 
     RaiseEvent(CtiCallsRetrievedPost, new CtiCallsRetrievedEventArgs(count),isAsync); 
     //........... 
     //........... 
    } 

    public event EventHandler<CtiCallsRetrievedEventArgs> CtiCallsRetrieved; 

    private void RaiseEvent(SendOrPostCallback callback, object state, bool isAsync) 
    { 
     if (isAsync) 
      createCallsAsync.Post(callback, state); 
     else 
      callback(state); 
    } 

    private void CtiCallsRetrievedPost(object state) 
    { 
     CtiCallsRetrievedEventArgs args = state as CtiCallsRetrievedEventArgs; 
     if (CtiCallsRetrieved != null) 
      CtiCallsRetrieved(this, args); 
    } 
} 

उत्तर के लिए सभी को धन्यवाद!

0

शायद नहीं सबसे सार्थक त्रुटि संदेश, मैंने देखा है इस के रूप में नीचे किसी तीसरे पक्ष कोड में होती हैं,

object obj = new object(); 
lock (obj) 
{ 
    //do something 

    Monitor.Exit(obj);//obj released 

}//exception happens here, when trying to release obj 
0

मैंने देखा है यह हो सकता है जब आप एक मॉनिटर का उपयोग कर कोड लॉक है, तो एक async कॉल कोड और आप इसे प्राप्त करते हैं, लॉक (ऑब्जेक्ट) का उपयोग करते समय आपको एक कंपाइलर त्रुटि मिलती है, हालांकि मॉनिटर.एन्टर (ऑब्जेक्ट) और मॉनीटर.एक्सिस्ट (ऑब्जेक्ट) के बीच कंपाइलर शिकायत नहीं करता है ... दुर्भाग्य से।

संबंधित मुद्दे