2012-12-16 13 views
18

मैंने एक नियंत्रक और क्रिया लिखा है जिसे मैं सेवा के रूप में उपयोग करता हूं। यह सेवा काफी महंगा कार्य करती है। यदि वर्तमान में वर्तमान में चल रही कार्रवाई हो रही है, तो मैं इस क्रिया तक पहुंच को सीमित करना चाहता हूं।एएसपीनेट एमवीसी कार्रवाई को कैसे लॉक करें?

वहाँ किसी भी तरह से बनाया गया एक asp.net MVC कार्रवाई लॉक करने के लिए है?

धन्यवाद

+0

क्या आप प्रति उपयोगकर्ता प्रति सत्र, प्रति उपयोगकर्ता इसे सीमित करना चाहते हैं? – Oshry

+1

आप कतारों की तलाश में हैं। –

+0

कुल सीमा, किसी को भी प्रवेश करने की अनुमति न दें अगर इसे – vondip

उत्तर

38

क्या आप इस तरह कुछ ढूंढ रहे हैं?

public MyController : Controller 
{ 
    private static object Lock = new object(); 

    public ActionResult MyAction() 
    { 
     lock (Lock) 
     { 
      // do your costly action here 
     }  
    } 
} 

ऊपर कार्रवाई को क्रियान्वित एक धागा वर्तमान में lock ब्लॉक के भीतर कोड संसाधित कर रहा है, तो किसी अन्य सूत्र नहीं कर पाएगा।

अद्यतन: यहाँ यह कैसे काम करता

विधि कोड हमेशा एक धागा द्वारा निष्पादित किया जाता है। भारी लोड किए गए सर्वर पर, 2 या अधिक अलग-अलग धागे दर्ज करना संभव है और समानांतर में विधि को निष्पादित करना प्रारंभ करना संभव है। सवाल के मुताबिक, यही वह है जिसे आप रोकना चाहते हैं।

नोट कैसे private Lock वस्तु static है। इसका मतलब है कि यह आपके नियंत्रक के सभी उदाहरणों में साझा किया जाता है। तो, भले ही ढेर पर बनाए गए इस नियंत्रक के 2 उदाहरण हैं, दोनों ही एक ही लॉक ऑब्जेक्ट साझा करते हैं।

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

lock कीवर्ड इसे रोकने के लिए इस्तेमाल किया जा सकता। जब कोई थ्रेड lock सेक्शन में लिपटे कोड के ब्लॉक में प्रवेश करता है, तो यह लॉक ऑब्जेक्ट (lock कीवर्ड, ए.के.ए. Lock, Jerry, या Samantha के बाद कोष्ठक में क्या है, जिसे static फ़ील्ड के रूप में चिह्नित किया जाना चाहिए) को "पिक्स अप" करता है। उस अवधि की अवधि के लिए जहां लॉक किया गया अनुभाग निष्पादित किया जा रहा है, यह लॉक ऑब्जेक्ट पर "रखता है"। जब थ्रेड लॉक सेक्शन से निकलता है, तो यह लॉक ऑब्जेक्ट को "छोड़ देता है"। जब तक यह लॉक ऑब्जेक्ट को छोड़ देता है तब तक थ्रेड लॉक ऑब्जेक्ट को उठाता है, अन्य सभी थ्रेड को कोड के लॉक सेक्शन में प्रवेश करने से रोका जाता है। असल में, वे "रुक गए" हैं जब तक वर्तमान में निष्पादित थ्रेड लॉक ऑब्जेक्ट को छोड़ देता है।

तो थ्रेड अपने MyAction विधि के शुरुआत में लॉक वस्तु को चुनता है। लॉक ऑब्जेक्ट को छोड़ने से पहले, थ्रेड बी भी इस विधि को निष्पादित करने का प्रयास करता है। हालांकि, यह लॉक ऑब्जेक्ट नहीं उठा सकता है क्योंकि यह पहले से ही थ्रेड ए द्वारा आयोजित किया गया है। इसलिए यह लॉक ऑब्जेक्ट को छोड़ने के लिए थ्रेड ए के लिए इंतजार कर रहा है।जब ऐसा होता है, तो थ्रेड बी तब लॉक ऑब्जेक्ट को उठाता है और कोड के ब्लॉक को निष्पादित करना शुरू करता है। जब थ्रेड बी ब्लॉक को निष्पादित कर लेता है, तो यह इस थ्रेड को संभालने के लिए दिए गए अगले थ्रेड के लिए लॉक ऑब्जेक्ट देता है।

... लेकिन मुझे यकीन है कि अगर यह है आप के लिए ...

क्या देख रहे आवश्यक रूप से अपने कोड किसी भी तेजी से चलाने के नहीं होगा इस दृष्टिकोण का उपयोग नहीं कर रहा हूँ। यह केवल यह सुनिश्चित करता है कि कोड का एक ब्लॉक केवल एक समय में 1 थ्रेड द्वारा निष्पादित किया जा सके। यह आम तौर पर प्रदर्शन कारणों से नहीं, समवर्ती कारणों के लिए प्रयोग किया जाता है। यदि आप प्रश्न में अपनी विशिष्ट समस्या के बारे में अधिक जानकारी प्रदान कर सकते हैं, तो इस से बेहतर जवाब हो सकता है।

याद रखें कि मैंने जो कोड ऊपर प्रस्तुत किया है, वह ब्लॉक को निष्पादित करने से पहले अन्य थ्रेड का इंतजार करेगा। यदि यह वही नहीं है जो आप चाहते हैं, और आप पूरी कार्रवाई को "छोड़ दिया" चाहते हैं, यदि इसे पहले से ही किसी अन्य थ्रेड द्वारा निष्पादित किया जा रहा है, तो ओश्री के उत्तर की तरह कुछ और उपयोग करें। आप इस जानकारी को कैश, सत्र या किसी अन्य डेटा स्टोरेज तंत्र में संग्रहीत कर सकते हैं।

+0

को किसी सत्र या कैश ऑब्जेक्ट में भी लॉक नहीं होना चाहिए? – vondip

+0

आपको क्यों लगता है कि इसे सत्र या कैश पर बने रहने की आवश्यकता होगी? – danludwig

+0

क्योंकि http सत्र-कम है, मुझे पूरे सत्र में लॉक को सहेजने की आवश्यकता होगी, नहीं? – vondip

2

आप [UseLock] अपने आवश्यकताओं के अनुसार की तरह एक कस्टम विशेषता सबसे आसान तरीका करने के लिए है कि कैश एक बूलियन मान कार्रवाई का संकेत देती है को बचाने होगा बनाते हैं और अपने कार्य

0

से पहले ही रख सकते हैं आवश्यक बीएल पहले से चल रहा:

if (System.Web.HttpContext.Current.Cache["IsProcessRunning"]) 
{ 
    System.Web.HttpContext.Current.Cache["IsProcessRunning"] = true; 
    // run your logic here 
    System.Web.HttpContext.Current.Cache["IsProcessRunning"] = false 
} 

बेशक आप ऐसा करते हैं, या कुछ इसी तरह की एक विशेषता के रूप में भी कर सकते हैं।

+3

यदि आप शर्त के अंदर दो धागे एक साथ हो सकते हैं। यह काफी अच्छा नहीं है मुझे डर है – vondip

+0

यदि आप शर्त के अंदर दो धागे एक साथ हो सकते हैं? यह व्यावहारिक रूप से असंभव है, लेकिन यदि आपको पूरी तरह से सुनिश्चित होना चाहिए, तो आप असाइनमेंट को कैश में लॉक कर सकते हैं। – Oshry

+6

यह एक बहुत ही गंदे दौड़ की स्थिति बग के लिए नुस्खा है। यदि कुछ भी खराब होता है तो दो धागे एक ही चीज़ को निष्पादित करते हैं, तो लॉक का उपयोग करें। – Vincent

5

पढ़ सकते हैं और इसके बाद के संस्करण जवाब मैं एक अलग समाधान चाहता था के साथ सहमति व्यक्त करने के बाद:

if (!Monitor.TryEnter(Lock, new TimeSpan(0))) 
{ 
    throw new ServiceBusyException("Locked!"); 
} 
try 
{ 
... 
} 
finally { 
    Monitor.Exit(Lock); 
} 

उपयोग एक ही स्थिर लॉक वस्तु: आप एक कार्रवाई के लिए एक दूसरी कॉल का पता लगाने चाहते हैं, Monitor.TryEnter का उपयोग जैसा कि @danludwig

0

द्वारा विस्तृत किया गया है, इसके बारे में मुझे सुझाव हैं।

1- https://github.com/madelson/DistributedLock प्रणाली विस्तृत ताला समाधान के साथ [DisableConcurrentExecution (1000)] विशेषता

2- Hangfire BackgroundJob.Enqueue।

प्रक्रिया समाप्त होने के लिए दो समाधान लंबित हैं। मैं एक ही समय अनुरोध करते समय त्रुटि फेंकना नहीं चाहता हूं।

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