هل أحتاج إلى الاتصال بالإندينفوك بعد مهلة؟

StackOverflow https://stackoverflow.com/questions/557918

  •  05-09-2019
  •  | 
  •  

سؤال

على صفحة ويب، أدعو طرفا ثالثا لا يسمح لي بتحديد مهلة برمجيا. أسمي BeginInvoke واستخدام Asyncwaithandle.waitone لانتظار مقدار الوقت المحدد.

إذا كانت أوقات المكالمة خارجا، فأنا ننتقل ونسيان مكالمة الخيط التي بدأت. سؤالي هو، هل ما زلت بحاجة إلى الاتصال EndInvoke بطريقة أو بأخرى في حالة مهلة؟ إن ملاحظة "الحذر" على صفحة MSDN هذه تجعلني أتساءل عما إذا كان ينبغي علي: http://msdn.microsoft.com/en-us/library/2e08f6yc(vs.71).aspx.

إذا كنت تعتقد أنني يجب أن يكون السؤال التالي هو إذا تم تجهيز صفحتي على الويب وإرجاعها إلى العميل قبل أن يعود الطرف الثالث، هل ستكون طريقة رد الاتصال حتى الآن الاستماع إلى التعليمات البرمجية؟ ألا تتوقف الخادم عن البحث عن Activitiy بمجرد الانتهاء من طلبي / استجابة؟

إليك الرمز الذي أستخدمه:

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;
    }
}
هل كانت مفيدة؟

المحلول 4

حسنا، لم أستطع تجاهل النصيحة التي رأيتها في كل مكان أنه إذا لم أتأكد من الاتصال بالأندينفوك، فقد تسرب بعض الموارد، لذلك اضطررت إلى محاولة الحصول على ذلك في النوم في الليل ولا تقلق كنت تقترب من الهاوية وبعد

الحل الذي وجدته يستخدم وظيفة رد الاتصال ASYNC. إذا عادت المكالمة في الوقت المناسب، فأنا أسمي EndInvoke هناك. إذا لم يكن الأمر كذلك، فستمركز الزر الخاص بي، واسمحوا وظيفة رد الاتصال 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.
        }       

    }
}

نصائح أخرى

من الممكن أنه إذا لم تتصل بالإندينفوك، فسوف تسرب بعض الموارد (مخصصة بواسطة BeginInvoke).

لذا أن تكون آمنة تماما، قم دائما بالاتصال EndInvoke () (الذي سيمنعه، لذا افعل ذلك في بعض الخلفية الخلفية، أو يمكنك التبديل إلى تمرير رد الاتصال حتى لا يحرق مؤشر ترابط أثناء الانتظار).

في الممارسة العملية، لا أعرف كم مرة يهم (أعتقد أن العديد من asyncrosults لن تسرب، لذلك قد تحصل على محظوظ وأن تكون آمنا في هذه الحالة).

كل هذا لا يوجد لديه ما يقرب من القيام به مع طلبي الاستجابة وخوادم الويب وغيرها، وهذا هو مجرد كيفية عمل نموذج البرمجة البدء / نهاية، بغض النظر عن التطبيق الذي تستخدمه فيه.

تحديث:
يبدو أنك بحاجة إلى دعوة endinvoke دائما للحصول على مكالمة ASYNC (ما لم يكن لديك سيطرتها .beGinInvoke) أو مخاطر تسرب الموارد.

هنا مناقشة على نفس الخطوط. وبعد هو الحل المقترح هو تفرخ مؤشر ترابط ينتظر المفوض أن يكمل فعلا واستدعاء EndInvoke. ومع ذلك، في حالة مهلة Loonong حقا، أعتقد أن الخيط سوف يتعطل فقط.

إنها حالة حافة لا تبدو موثقة جيدا ... ربما لم يكن من المفترض أن تحدث مهلة Coz .. حالات استثنائية

للحالة العامة لنمط .NET ASYNC، استدعاء EndXXX عندما لا ترغب في إكمال العملية، ستكون عملية بدء التشغيل مع BeXXX ستكون خطأ لأنه إذا تم استدعاء EndXXX قبل أن تكون العملية قد أكملت، فعليك حظرها حتى يكملها. التي ليست مساعدة كبيرة في المهلة.

قد يكون API محدد مختلفا (مثل WinForms بشكل صريح لا يتطلب EndInvoke).

انظر §9.2 من "إرشادات تصميم الإطار" (2nd ed). أو MSDN..

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top