2009-02-17 14 views
8

एक वेब पेज पर, मैं एक तीसरी पार्टी को बुला रहा हूं जो मुझे समय-समय पर प्रोग्रामआउट सेट करने की अनुमति नहीं देता है। मैं BeginInvoke को कॉल करता हूं और निर्दिष्ट समय की प्रतीक्षा करने के लिए AsyncWaitHandle.WaitOne का उपयोग करता हूं।क्या मुझे टाइमआउट के बाद एंडइवोक को कॉल करने की आवश्यकता है?

यदि कॉल का समय समाप्त हो गया है, तो मैं आगे बढ़ने वाले थ्रेड कॉल के बारे में सोचता हूं और भूल जाता हूं। मेरा सवाल है, क्या मुझे अभी भी टाइमआउट स्थिति में किसी भी तरह EndInvoke को कॉल करना है? इस एमएसडीएन पेज पर "सावधानी" टिप्पणी मुझे आश्चर्यचकित करती है कि मुझे: http://msdn.microsoft.com/en-us/library/2e08f6yc(VS.71).aspx

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

public class RemotePaymentProcessor 
{ 
    private delegate string SendProcessPaymentDelegate(string creditCardNumber); 

    private string SendProcessPayment(string creditCardNumber) 
    { 
     string response = string.Empty; 
     // call web service 
     SlowResponseService.SlowResponseService srs = new WebServiceTimeout.SlowResponseService.SlowResponseService(); 
     response = srs.GetSlowResponse(creditCardNumber); 
     return response; 
    } 

    public string ProcessPayment(string creditCardNumber, int timeoutMilliseconds) 
    { 
     string response = string.Empty; 

     SendProcessPaymentDelegate sppd = new SendProcessPaymentDelegate(SendProcessPayment); 
     IAsyncResult ar = sppd.BeginInvoke(creditCardNumber, null, new object()); 
     if (!ar.AsyncWaitHandle.WaitOne(timeoutMilliseconds, false)) 
     { 
      // Async call did not return before timeout 
      response = "TIMEOUT"; 
     } 
     else 
     { 
      // Async call has returned - get response 
      response = sppd.EndInvoke(ar); 
     } 
     return response; 
    } 
} 

उत्तर

0

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

मैंने जो समाधान पाया वह एक एसिंक कॉलबैक फ़ंक्शन का उपयोग करता था। अगर कॉल समय पर लौटा, तो मैं एंडइनवोक को वहां कॉल करता हूं। यदि नहीं, तो मैं अपना बटन क्लिक जारी रखता हूं, और async कॉलबैक फ़ंक्शन को EndInvoke के साथ गड़बड़ी को साफ करने देता हूं।

किसी वेब ऐप के बारे में अपने स्वयं के प्रश्न का उत्तर देने के लिए और "क्या कोई भी समय समाप्त होने और आगे बढ़ने के बाद सुनेंगे", मैंने पाया कि वे करेंगे - भले ही मैं समय निकालकर आगे बढ़ूं, अगर मैंने बाद में देखा आउटपुट, कि async कॉल वापस लौटाएगा और कॉल बैक फ़ंक्शन चलाएगा, भले ही मैं क्लाइंट को आउटपुट वापस कर चुका हूं।

मैं मैं क्या में पाए जाने वाले कुछ प्रयोग किया है: http://www.eggheadcafe.com/tutorials/aspnet/847c94bf-4b8d-4a66-9ae5-5b61f049019f/basics-make-any-method-c.aspx

... साथ ही कॉलबैक सामान मैं कहीं भी पाई के साथ संयोजन के रूप में। मैंने नीचे जो किया है उसका एक छोटा सा नमूना कार्य यहां दिया गया है। यह है कि मैं क्या हर किसी के इनपुट !:

public class RemotePaymentProcessor 
{  
    string currentResponse = string.Empty; 

    private delegate string SendProcessPaymentDelegate(string creditCardNumber);  
    private string SendProcessPayment(string creditCardNumber)  
    {   
     SlowResponseService.SlowResponseService srs = new WebServiceTimeout.SlowResponseService.SlowResponseService();   
     string response = srs.GetSlowResponse(creditCardNumber);   
     return response;  
    }  

    public string ProcessPayment(string creditCardNumber, int timeoutMilliseconds)  
    {   
     string response = string.Empty;   
     SendProcessPaymentDelegate sppd = new SendProcessPaymentDelegate(SendProcessPayment);   
     IAsyncResult ar = sppd.BeginInvoke(creditCardNumber, new AsyncCallback(TransactionReturned), sppd);   
     if (!ar.AsyncWaitHandle.WaitOne(timeoutMilliseconds, false))   
     {    
      // Async call did not return before timeout    
      response = "TIMEOUT";   
     }   
     else    
     {    
      // Async call has returned - get response    
      response = sppd.EndInvoke(ar);   
     }   

     currentResponse = response; // Set class variable 
     return response;  
    } 

    private void TransactionReturned(IAsyncResult ar) 
    { 
     string response = string.Empty; 

     // Get delegate back out of Async object 
     SendProcessPaymentDelegate sppd = (SendProcessPaymentDelegate)ar.AsyncState; 

     // Check outer class response status to see if call has already timed out 
     if(currentResponse.ToUpper().Equals("TIMEOUT")) 
     { 
      // EndInvoke has not yet been called so call it here, but do nothing with result 
      response = sppd.EndInvoke(ar); 
     } 
     else 
     { 
      // Transaction must have returned on time and EndInvoke has already been called. Do nothing. 
     }  

    } 
} 
1

अपडेट::
लगता है जैसे आप एक async कॉल के लिए call EndInvoke always करने की जरूरत है (जब तक कि इसकी Control.BeginInvoke) या जोखिम लीक संसाधनों

यहाँ कोड मैं का उपयोग कर रहा है।

यहां a discussion that is on the same lines है। समाधान का सुझाव है कि एक धागे को उखाड़ फेंकना जो प्रतिनिधि को वास्तव में पूरा करने और एंडइवोक को कॉल करने का इंतजार करेगा। हालांकि वास्तव में लुओंग टाइमआउट के मामले में मुझे लगता है कि धागा बस लटका होगा।

इसकी बढ़त मामले कि प्रलेखित किया जाना है कि अच्छी तरह से ... शायद coz समय समाप्ति नहीं जा सकते हो प्रतीत नहीं होता है .. असाधारण मामलों

2

यह है कि यदि आप EndInvoke, आप कॉल नहीं है संभव है कुछ संसाधन रिसाव करेंगे (BeginInvoke द्वारा आवंटित)।

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

प्रैक्टिस में मुझे नहीं पता कि यह कितनी बार मायने रखता है (मुझे लगता है कि कई AsyncResults रिसाव नहीं होंगे, इसलिए आप भाग्यशाली हो सकते हैं और इस उदाहरण में सुरक्षित रह सकते हैं)।

यह सब अनुरोध-प्रतिक्रिया और वेब सर्वर और whatnot के साथ क्या करने के लिए लगभग कुछ भी नहीं है, यह सिर्फ कैसे क्या आवेदन आप इसे में उपयोग कर रहे हैं शुरू/अंत प्रोग्रामिंग मॉडल काम करता है, की परवाह किए बिना।

+0

का अनुरोध-प्रतिक्रिया के संबंध में के लिए धन्यवाद में पाए जाने वाले कुछ को जोड़ती है: अगर मैं एक कॉलबैक विधि गुजरती हैं, लेकिन मतलब समय में मेरी buttonclick समारोह को पूरा करने और ग्राहक के लिए लौटने के लिए, वहाँ है कोई भी सुन रहा है जब BeginInvoke धागा देता है? एक स्थानीय ऐप में, यदि मेन() ने ऐप बंद कर दिया और बंद कर दिया, तो कॉलबैक कभी नहीं निकाल दिया गया। – Chad

0

के लिए .NET async पैटर्न का सामान्य मामला, EndXXX को कॉल करते समय, जब आप BeingXXX के साथ शुरू होने वाले ऑपरेशन को पूरा नहीं करना चाहते हैं तो यह गलती होगी क्योंकि अगर ऑपरेशन पूरा होने से पहले एंडोक्सएक्स को कॉल किया जाता है तो इसे पूरा होने तक ब्लॉक करना चाहिए। जो एक टाइमआउट के लिए ज्यादा मदद नहीं है।

एक विशिष्ट एपीआई अलग हो सकती है (उदा। WinForms स्पष्ट रूप से EndInvoke की आवश्यकता नहीं है)।

"फ्रेमवर्क डिज़ाइन दिशानिर्देश" (2 संस्करण) के §9.2 देखें। या msdn

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

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