2010-02-02 12 views
12

में सिस्टम म्यूटेक्स कैसे बना सकता हूं, मैं एक ही अप्रबंधित संसाधन का उपयोग करके एकाधिक प्रक्रियाओं को समन्वयित करने के लिए सिस्टम/मल्टीप्रोसेस म्यूटेक्स कैसे बना सकता हूं।मैं सी #

पृष्ठभूमि: मैंने एक ऐसी प्रक्रिया लिखी है जो एक फ़ाइल प्रिंटर का उपयोग करती है, जिसका उपयोग केवल एक ही समय में एक प्रक्रिया द्वारा किया जा सकता है। अगर मैं कंप्यूटर पर चल रहे कई प्रोग्रामों पर इसका उपयोग करना चाहता था, तो मुझे सिस्टम में इसे सिंक्रनाइज़ करने का एक तरीका चाहिए।

+0

यहाँ एक लिपटे वर्ग कि इंटर प्रक्रिया लॉकिंग और परित्यक्त म्युटेक्स स्थिति https://github.com/blinemedical/Inter-process-mutex संभालती – devshorts

उत्तर

26

आप सिस्टम का उपयोग कर सकते हैं। थ्रेडिंग। म्यूटेक्स क्लास, जिसमें नामित सिस्टम mutex खोलने के लिए ओपनएक्सस्टिंग विधि है।

कि इस सवाल का जवाब नहीं है:

मैं एक प्रणाली/मल्टीप्रोसेस Mutex

सिस्टम-वाइड म्युटेक्स बनाने के लिए कैसे बना सकते हैं, System.Threading.Mutex फोन कन्स्ट्रक्टर जो एक तर्क के रूप में एक स्ट्रिंग लेता है। इसे 'नामित' म्यूटेक्स के रूप में भी जाना जाता है। यदि वह मौजूद है देखने के लिए, मैं से पकड़ की कोशिश एक और अधिक सुंदर विधि को खोजने के लिए प्रतीत नहीं कर सकते हैं:

System.Threading.Mutex _mutey = null; 
try 
{ 
    _mutey = System.Threading.Mutex.OpenExisting("mutex_name"); 
    //we got Mutey and can try to obtain a lock by waitone 
    _mutey.WaitOne(); 
} 
catch 
{ 
    //the specified mutex doesn't exist, we should create it 
    _mutey = new System.Threading.Mutex("mutex_name"); //these names need to match. 
} 

अब, एक अच्छा प्रोग्रामर होने के लिए, आप के लिए, जब आप प्रोग्राम खत्म हो, इस म्युटेक्स जारी की जरूरत

_mutey.ReleaseMutex(); 

या, आप इसे छोड़ सकते हैं, जब आपका धागा निकलता है तो उसे 'त्याग दिया' कहा जाएगा, और दूसरी प्रक्रिया को इसे बनाने की अनुमति होगी।

[संपादित करें]

अंतिम वाक्य को एक तरफ ध्यान दें म्युटेक्स कि छोड़ दिया जाता है का वर्णन है, जब एक और धागा म्युटेक्स प्राप्त कर लेता है, अपवाद System.Threading.AbandonedMutexException उसे कह फेंक दिया जाएगा के रूप में इसे छोड़ दिया राज्य में मिला था।

[संपादित करें TWO]

मुझे यकीन है कि क्यों मुझे लगता है कि जिस तरह से साल पहले सवाल का जवाब नहीं कर रहा हूँ; एक कन्स्ट्रक्टर ओवरलोड (और था) है जो मौजूदा म्यूटेक्स की जांच में बहुत बेहतर है। असल में, मैंने जो कोड दिया वह दौड़ की स्थिति में प्रतीत होता है! (और आप सभी को शर्मिंदा करने के लिए आप पर शर्मिंदा नहीं है! :-P)

यहां दौड़ की स्थिति है: दो प्रक्रियाओं की कल्पना करें, वे दोनों एक ही समय में मौजूदा म्यूटेक्स को खोलने का प्रयास करते हैं, और दोनों कोड के पकड़ अनुभाग में जाते हैं । फिर, प्रक्रियाओं में से एक म्यूटेक्स बनाता है और बाद में खुशी से रहता है। हालांकि, दूसरी प्रक्रिया म्यूटेक्स बनाने की कोशिश करती है, लेकिन इस बार यह पहले से ही बनाई गई है! एक mutex की यह जांच/निर्माण परमाणु होना चाहिए।

http://msdn.microsoft.com/en-us/library/bwe34f1k(v=vs.90).aspx

तो ...

var requestInitialOwnership = false; 
bool mutexWasCreated; 
Mutex m = new Mutex(requestInitialOwnership, 
     "MyMutex", out mutexWasCreated); 

मुझे लगता है कि चाल यहाँ ऐसा लगता है कि यह है कि आप कि आप वास्तव में जरूरत नहीं है (मेरे लिए एक डिजाइन दोष तरह दिखता है) का विकल्प होता है है। यदि आप के लिए true भेजते हैं तो आप कभी-कभी यह नहीं बता सकते कि क्या आप म्यूटेक्स के स्वामी हैं। यदि आप true पास करते हैं और ऐसा लगता है कि आपकी कॉल ने म्यूटेक्स बनाया है, तो जाहिर है कि आप इसका स्वामी हैं (दस्तावेज़ीकरण द्वारा पुष्टि की गई)। यदि आप true पास करते हैं और आपकी कॉल ने म्यूटेक्स नहीं बनाया है, तो आप जानते हैं कि म्यूटेक्स पहले से ही बनाया गया था, आपको नहीं पता कि कुछ अन्य प्रक्रिया या धागा जो शायद म्यूटेक्स को बनाते हैं, वर्तमान में म्यूटेक्स का मालिक है। इसलिए, यह सुनिश्चित करने के लिए कि आपके पास यह है, आपको WaitOne करना होगा। लेकिन फिर, आप कितने Release एस करते हैं? अगर आपको मिलने पर कुछ अन्य प्रक्रियाओं में म्यूटेक्स का स्वामित्व होता है, तो केवल WaitOne पर आपकी स्पष्ट कॉल Release डी होना चाहिए। यदि आपके कन्स्ट्रक्टर को कॉल करने के कारण आपको म्यूटेक्स का स्वामित्व हुआ है, और आपने स्पष्ट रूप से WaitOne कहा है, तो आपको दो Release एस की आवश्यकता होगी।

मैं कोड में इन शब्दों डाल देता हूँ:

var requestInitialOwnership = true; /*This appears to be a mistake.*/ 
bool mutexWasCreated; 
Mutex m = new Mutex(requestInitialOwnership, 
     "MyMutex", out mutexWasCreated); 

if (!mutexWasCreated) 
{ 
    bool calledWaitOne = false; 
    if (! iOwnMutex(m)) /*I don't know of a method like this*/ 
    { 
     calledWaitOne = true; 
     m.WaitOne(); 
    } 

    doWorkWhileHoldingMutex(); 

    m.Release(); 
    if (calledWaitOne) 
    { 
     m.Release(); 
    } 
} 

जब से मैं कि क्या आप वर्तमान में म्युटेक्स ही परीक्षण करने के लिए एक तरह से नहीं देखते हैं, मैं दृढ़ता से सुझाव है कि आप इतना है कि निर्माता को false पारित करेंगे आप जानते हैं कि आपके पास म्यूटेक्स नहीं है, और आप जानते हैं कि Release पर कॉल करने के लिए कितनी बार।

+0

+1 ग्रेट उत्तर। वह कोड स्निपेट बहुत उपयोगी है। – LeopardSkinPillBoxHat

+1

.NET Framework 4.5 ने ['TryOpenExisting'] (http://msdn.microsoft.com/en-us/library/hh194641.aspx) विधि जोड़ा जो म्यूटेक्स पहले से मौजूद नहीं है, तो अपवाद नहीं फेंकता है। –

+0

@ 280Z28 अनुस्मारक के लिए धन्यवाद। .NET FX 3.5 की समकक्ष क्षमता है (हालांकि मैं तर्क देता हूं कि इसमें एक डिज़ाइन दोष है) जिसका मैंने अपने मूल उत्तर में उल्लेख नहीं किया था और जिसे मैंने दोबारा संपादित करने में ऊपर वर्णित किया था। –

0

अपने कोड को देखे बिना यह विशिष्ट सलाह देने के लिए कठिन है, लेकिन सी # में एक म्युटेक्स वर्ग है

MSDN

3

आप System.Threading.Mutex वर्ग है, जो एक नामित प्रणाली म्युटेक्स खोलने के लिए एक OpenExisting विधि है उपयोग कर सकते हैं ।

+0

धन्यवाद है, एहसास नहीं था कि विधि मैं क्या चाहता था। –

0

लिनक्स के तहत मोनो का उपयोग करके ऊपर वर्णित सिस्टम म्यूटेक्स का उपयोग करके मुझे शुभकामनाएं नहीं मिली हैं। मैं शायद कुछ सरल गलत कर रहा हूं लेकिन निम्न कार्य अच्छी तरह से काम करता है और अगर प्रक्रिया अप्रत्याशित रूप से बाहर निकलती है (हत्या -9)। टिप्पणियों या आलोचनाओं को सुनने में रुचि होगी।

class SocketMutex{ 
    private Socket _sock; 
    private IPEndPoint _ep; 
    public SocketMutex(){ 
     _ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 7177); 
     _sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
     _sock.ExclusiveAddressUse = true; // most critical if you want this to be a system wide mutex 
    } 

    public bool GetLock(){ 
     try{   
      _sock.Bind(_ep); // 'SocketException: Address already in use' 
     }catch(SocketException se){ 
      Console.Error.WriteLine ("SocketMutex Exception: " se.Message); 
      return false; 
     } 
     return true; 

    } 
}