2010-01-05 14 views
11

जब एक ही ClientBase<T> उदाहरण एकाधिक डब्ल्यूसीएफ सेवा कॉल के लिए उपयोग किया जाता है, तो यह एक चैनल को एक दोषपूर्ण स्थिति (यानी जब सेवा डाउन हो) में मिल सकती है।दोषपूर्ण डब्ल्यूसीएफ चैनलों को कैसे ठीक किया जाए?

सेवा फिर से आने पर मैं स्वचालित रूप से चैनल को ठीक करना चाहता हूं। मुझे मिला एकमात्र तरीका प्रत्येक विधि कॉल से पहले निम्नलिखित कोड को कॉल करना है:

if (clientBase.InnerChannel.State == CommunicationState.Faulted) 
{ 
     clientBase.Abort(); 
     ((IDisposable)clientBase).Dispose(); 
     clientBase = new SampleServiceClientBase(); 
} 

मुझे यह महसूस हुआ कि यह करने का यह सही तरीका नहीं है। किसी को भी बेहतर विचार मिला?

उत्तर

18

आप नहीं कर सकते। एक बार चैनल की गलती हो जाने के बाद, यह अच्छा के लिए दोषी है। आपको एक नया चैनल बनाना होगा। डब्ल्यूसीएफ चैनल स्टेटफुल (बोलने के तरीके में) हैं, इसलिए एक दोषपूर्ण चैनल का मतलब है कि राज्य दूषित हो सकता है।

आप क्या कर सकते तर्क आप एक उपयोगिता विधि में उपयोग कर रहे हैं डाल दिया है:

public static class Service<T> where T : class, ICommunicationObject, new() 
{ 
    public static void AutoRepair(ref T co) 
    { 
     AutoRepair(ref co,() => new T()); 
    } 

    public static void AutoRepair(ref T co, Func<T> createMethod) 
    { 
     if ((co != null) && (co.State == CommunicationState.Faulted)) 
     { 
      co.Abort(); 
      co = null; 
     } 
     if (co == null) 
     { 
      co = createMethod(); 
     } 
    } 
} 

तो आप निम्नलिखित के साथ अपने सेवा शुरू कर सकते हैं:

Service<SampleServiceClient>.AutoRepair(ref service, 
    () => new SampleServiceClient(someParameter)); 
service.SomeMethod(); 

या आप करना चाहते हैं डिफ़ॉल्ट पैरामीटर रहित कन्स्ट्रक्टर का उपयोग करें, बस:

Service<SampleServiceClient>.AutoRepair(ref service); 
service.SomeMethod(); 

चूंकि यह उस मामले को भी संभालता है जहां टी वह सेवा null है, आपको इसे कॉल करने से पहले सेवा को प्रारंभ करने की आवश्यकता नहीं है।

बहुत अच्छा मैं पेशकश कर सकता हूं। शायद किसी और के पास एक बेहतर तरीका है।

+1

क्या आपको आईडीस्पोजेबल को लागू करने के लिए टी की भी आवश्यकता है? –

+0

@ डेविड गार्डिनर: यदि यह 'ICommunicationObject' लागू नहीं करता है। डब्ल्यूसीएफ चैनलों पर 'निपटान' कार्यान्वयन वास्तव में समस्या का हिस्सा है। – Aaronaught

+0

लेकिन ICommunicationObject इंटरफ़ेस (http://msdn.microsoft.com/en-us/library/system.servicemodel.icommunicationobject.aspx) IDISposable लागू नहीं करता है - इसलिए ऊपर दिया गया उदाहरण IDISposable को कास्टिंग के बिना काम नहीं करेगा। –

0

यही वह है जो मैं वर्तमान में कर रहा हूं, लेकिन मैं यह नहीं कह सकता कि यह सबसे अच्छा विकल्प है।

जब मैं कॉल पर अपवाद पकड़ा जाता हूं तो मैं प्रॉक्सी को फिर से बना देता हूं।

try 
{ 
    ListCurrentProcesses(); 
} 
catch (TypeLoadException ex) 
{ 
    Debug.Print("Oops: " + ex.Message); 
    m_Proxy = new ProcessManagerProxy(); 
} 
catch (EndpointNotFoundException endpointEX) 
{ 
    Debug.Print("Oops: " + endpointEX.Message); 
    m_Proxy = new ProcessManagerProxy(); 
} 
catch (CommunicationException communicationEx) 
{ 
    Debug.Print("Oops: " + communicationEx.Message); 
    m_Proxy = new ProcessManagerProxy(); 
} 
+0

कभी भी 'सिस्टम अपवाद' को पकड़ें, ** विशेष रूप से ** यदि आप फिर से फेंक रहे नहीं हैं। उस पेड़ में 'OutOfMemoryException' और' StackOverflowException' जैसे उदाहरण शामिल हैं। इसके अलावा, आप यहां पुराने चैनल का सही ढंग से निपटान नहीं कर रहे हैं। – Aaronaught

+0

समझा। यह सिर्फ एक त्वरित उदाहरण था। क्या आपको स्पष्ट रूप से निपटाने के बजाय चैनल को एकत्रित करने में एक बड़ी समस्या दिखाई देती है? मुझे लगता है कि हम हारने से पहले 1000 बार इस ऑपरेशन को पुनः प्रयास नहीं करेंगे। –

+0

मैंने कोशिश की और इससे अधिक समस्याएं उत्पन्न हुईं –

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