ASP MVC: IController Dispose () कब कहा जाता है?


83

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

उसके प्रकाश में, मैंने तब से अपने आधार नियंत्रक में यह परिवर्तन किया है:

public class MyBaseController : Controller
{
    private ConfigurationManager configManager;  // Manages the data context.

    public MyBaseController()
    {
         configManager = new ConfigurationManager();
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (this.configManager != null)
            {
                this.configManager.Dispose();
                this.configManager = null;
            }
        }

        base.Dispose(disposing);
    }
}

अब, मेरे दो सवाल हैं:

  1. क्या मैं एक दौड़ की स्थिति का परिचय दे रहा हूं? चूँकि जो दृश्य के मापदंडों को उजागर configManagerकरता है, उसे प्रबंधित DataContextकरता है IQueryable<>, मुझे यह सुनिश्चित करने की आवश्यकता है कि Dispose()व्यू रेंडरिंग समाप्त होने से पहले नियंत्रक को नहीं बुलाया जाएगा।
  2. क्या MVC फ्रेमवर्क Dispose()नियंत्रक को देखने से पहले या बाद में कॉल किया जाता है? या, क्या MVC फ्रेमवर्क कचरा उठाने वाले तक छोड़ देता है?

2
मैं इस एक के जवाब के लिए आगे देखो sooo हूँ! महान सवाल!
डैनियल इलियट

अन्य कोड (तुम्हारा या ASP.NET MVC के ..) को देखे बिना आपको configManager को बाहर निकालने की आवश्यकता क्यों है? क्या इससे कुछ मदद मिलती है? किसी भी "DUH" मुझे पहले अच्छी तरह से सोचें ..
आंद्रेई R Octnea

मेरा मतलब है कि एक सामान्य मामले में एक दौड़ की स्थिति को आसानी से हटाया जा सकता है। इस विशेष मामले में मुझे संदेह है कि एक नियंत्रक उदाहरण का उपयोग एक से अधिक थ्रेड द्वारा किया जाएगा और इसलिए दौड़ की स्थिति का कोई जोखिम नहीं है।
आंद्रेई रैनिया

1
@Andrei: यह केवल रक्षात्मक-कोडिंग का एक सा है। यह मुझे दो बार डेटाबेस कनेक्शन को डिस्पोज़ करने से रोकता है, अगर मेरी डिस्पोज़ विधि को दो बार कॉल किया जाता है।
जॉन गिएट्ज़ेन

1
@Andrei: खैर, मेरी राय में "इग्नोरिंग" और "कॉलिंग डिस्पोज़ ऑन चाइल्ड ऑब्जेक्ट्स एनीवेज" पूरी तरह से अलग हैं। इसलिए जांच की जाएगी।
जॉन गीटजेन

जवाबों:


70

दृश्य के प्रतिपादन के बाद डिस्पोज़ को कहा जाता है, हमेशा

कॉल करने के लिए दृश्य प्रस्तुत किया गया है ActionResult.ExecuteResult। इसे (अप्रत्यक्ष रूप से) कहा जाता है ControllerActionInvoker.InvokeAction, जो बदले में कहा जाता है ControllerBase.ExecuteCore

चूंकि नियंत्रक कॉल स्टैक में होता है जब दृश्य प्रदान किया जाता है, तब इसे निपटाया नहीं जा सकता।


महान, क्या आपके पास प्रलेखन है? मैं सिर्फ यकीन करना चाहता हूं।
बजे जॉन गिएटजेन

महान! यह समझाने वाले एक डॉक्टर को खोजने के लिए बहुत अच्छा होगा। लेकिन विस्तारित उत्तर वास्तव में सुकून देने वाला था। कोड बेहतर डॉक है। : D
CSA

37

बस क्रेग स्टंट के जवाब पर विस्तार करने के लिए :

जब नियंत्रक निपटाया जाता है, तो नियंत्रक कार्यभार संभालता है। IControllerFactory इंटरफ़ेस को लागू करते समय, लागू करने के लिए आवश्यक विधियों में से एक है रिलीज़कंट्रोलर।

मुझे यकीन नहीं है कि आप क्या नियंत्रक का उपयोग कर रहे हैं, चाहे आप अपना खुद का रोल करें, लेकिन रिफ्लेक्टर में DefaultControllerFactory को देखते हुए, रिलीज़कंट्रोलर विधि इस तरह से लागू की जाती है:

public virtual void ReleaseController(IController controller)
{
    IDisposable disposable = controller as IDisposable;
    if (disposable != null)
    {
        disposable.Dispose();
    }
}

एक IController संदर्भ में पारित किया जाता है, यदि वह नियंत्रक IDisposable लागू करता है, तो उस नियंत्रक निपटान विधि को कहा जाता है। इसलिए, यदि आपके पास अनुरोध समाप्त होने के बाद आपके पास कुछ भी है, जिसका निपटान किया गया है, जो कि दृश्य प्रदान किए जाने के बाद है। किसी भी संसाधन को जारी करने के लिए आईडीसोफरेबल से बाहर निकलें और अपने तर्क को डिस्पोज विधि में डालें।

रिलीज़कंट्रोलर पद्धति को System.Web.Mvc.MvcHandler द्वारा बुलाया जाता है जो अनुरोध को संभालता है और यह IHttpHandler को लागू करता है। ProcessRequest इसे दिए गए HttpContext को लेता है और कार्यान्वित कंट्रोलरफैक्टरी में कॉल करके अनुरोध को संभालने के लिए नियंत्रक खोजने की प्रक्रिया शुरू करता है। यदि आप ProcessRequest पद्धति में देखते हैं, तो आपको अंतत: ब्लॉक दिखाई देगा जो कंट्रोलरफैक्टरी के रिलीज़कंट्रोलर को कॉल करता है। यह केवल तभी कहा जाता है जब नियंत्रक ने ViewResult लौटा दिया हो।


बहुत बढ़िया जवाब। मैं यह पता नहीं लगा सका कि एक नियंत्रक वस्तु का प्रत्यक्ष उदाहरण मुझे उस पर Dispose () कॉल करने की अनुमति क्यों नहीं देगा, लेकिन ऐसा लग रहा है कि मुझे आईडीसॉर्पोरेट इंटरफ़ेस का उपयोग करके इसका एक नया उदाहरण बनाने की आवश्यकता है। यह मेरे लिए काम किया!
मेगामैट

तो ... HttpContextएक पुरुष है? अब मैं वास्तव में भ्रमित हूँ।
Chef_Code
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.