2013-05-10 3 views
5

मैं निष्क्रिय प्रतिकृति के साथ एक प्रोजेक्ट विकसित कर रहा हूं जहां सर्वर स्वयं के बीच संदेशों का आदान-प्रदान करता है। प्रत्येक सर्वर के स्थान हर दूसरे सर्वर द्वारा जाने जाते हैं।सक्रियकर्ता को कॉल करने के बाद कोई वस्तु मौजूद है या नहीं। GetObject

तो, ऐसा हो सकता है कि जब कोई सर्वर आता है, तो यह अन्य सर्वरों की जांच करेगा, जो अभी तक नहीं आए हैं। जब मैं Activator.GetObject पर कॉल करता हूं, तो क्या यह पता लगाने का एकमात्र तरीका है कि अन्य सर्वर ऑब्जेक्ट पर एक विधि का आह्वान करके नीचे आते हैं, और IOException (जैसे नीचे दिया गया उदाहरण) की अपेक्षा करते हैं?

try 
{ 
    MyType replica = (MyType)Activator.GetObject(
    typeof(IMyType), 
    "tcp://localhost:" + location + "/Server"); 

    replica.ping(); 
} 
catch (IOEXception){} // server is down 

मैं यह करने के लिए और इसे समय की (भले ही धीमी है) सबसे अधिक काम करता है, लेकिन कभी कभी यह एक तरीका है पर ब्लॉक की प्रक्रिया के दौरान NegotiateStream.ProcessRead कहा जाता है, और मैं क्यों समझ में नहीं कर सकते हैं ...

+0

आपका मतलब है IMyType प्रतिकृति = IMyType) Activator.GetObject (typeof (IMyType), "टीसीपी: // स्थानीय होस्ट:" + स्थान + "/ सर्वर") ;? – AngelCastillo

+0

उस मामले में कोई समस्या नहीं है, MyType IMyType इंटरफ़ेस लागू करता है। और जैसा कि मैंने कहा, यह ज्यादातर बार काम करता है इसलिए मुझे नहीं लगता कि यह समस्या हो सकती है! –

उत्तर

1

जब कोई सर्वर डाउन हो जाता है, तो टाइमआउट हमेशा मेरे लिए धीमा रहा है (एक टीसीपी चैनल का उपयोग करके, जो आपको .NET Remoting में टाइमआउट को ठीक से सेट करने नहीं देता है)। नीचे मैं अपने पिंग समारोह का उपयोग करने के लिए एक समाधान (यह संभावना अपनी आवश्यकताओं के लिए थोड़ा जटिल है, तो मैं भागों है कि आप के लिए कोई फर्क के बारे में समझाएंगे) है:

[System.Diagnostics.DebuggerHidden] // ignore the annoying breaks when get exceptions here. 
    internal static bool Ping<T>(T svr) 
    { 
    // Check type T for a defined Ping function 
    if (svr == null) return false; 
    System.Reflection.MethodInfo PingFunc = typeof(T).GetMethod("Ping"); 
    if (PingFunc == null) return false; 

    // Create a new thread to call ping, and create a timeout of 5 secons 
    TimeSpan timeout = TimeSpan.FromSeconds(5); 
    Exception pingexception = null; 
    System.Threading.Thread ping = new System.Threading.Thread(
     delegate() 
     { 
      try 
      { 
       // just call the ping function 
       // use svr.Ping() in most cases 
       // PingFunc.Invoke is used in my case because I use 
       // reflection to determine if the Ping function is 
       // defined in type T 
       PingFunc.Invoke(svr, null); 
      } 
      catch (Exception ex) 
      { 
       pingexception = ex; 
      } 
     } 
    ); 

    ping.Start(); // start the ping thread. 
    if (ping.Join(timeout)) // wait for thread to return for the time specified by timeout 
    { 
     // if the ping thread returned and no exception was thrown, we know the connection is available 
     if (pingexception == null) 
      return true; 
    } 

    // if the ping thread times out... return false 
    return false; 
    } 

उम्मीद है कि टिप्पणियों क्या मैं यहाँ कर समझाने, लेकिन मैं आपको पूरे समारोह का टूटना दूंगा। यदि आप रुचि नहीं रखते हैं, तो बस जहां मैं पिंग थ्रेड की व्याख्या करता हूं वहां जाएं।

DebuggerHidden गुण

मैं DebuggerHidder विशेषता निर्धारित क्योंकि जब डीबगिंग, अपवाद यहाँ लगातार पिंग धागा में फेंक दिया जा सकता है, और वे उम्मीद कर रहे हैं। इस समारोह को डीबग करना आवश्यक है, इस पर टिप्पणी करना इतना आसान है।

मैं प्रतिबिंब और एक सामान्य प्रकार

'svr' पैरामीटर एक पिंग समारोह के साथ एक प्रकार का होने की उम्मीद है क्यों इस्तेमाल करते हैं। मेरे मामले में, मेरे पास एक सामान्य पिंग फ़ंक्शन के साथ सर्वर पर लागू कुछ अलग-अलग रिमोटेबल इंटरफेस हैं। इस तरह, मैं सिर्फ एक प्रकार को कास्ट या निर्दिष्ट किए बिना पिंग (svr) को कॉल कर सकता हूं (जब तक रिमोट ऑब्जेक्ट को स्थानीय रूप से 'ऑब्जेक्ट' के रूप में तत्काल नहीं किया जाता है)। असल में, यह सिर्फ वाक्य रचनात्मक सुविधा के लिए है।

पिंग थ्रेड

आप एक स्वीकार्य समय समाप्ति निर्धारित करने के लिए चाहते हैं जो कुछ भी तर्क का उपयोग कर सकते हैं, मेरे मामले में, 5 सेकंड अच्छा है। मैं 5 सेकंड के मान के साथ टाइमस्पेन 'टाइमआउट' बनाता हूं, एक अपवाद पिंगेसेप्शन, और 'svr.Ping()' को कॉल करने का प्रयास करने वाला एक नया थ्रेड बनाता है, और 'svr' को कॉल करते समय जो भी अपवाद फेंक दिया जाता है, उसे 'पिंगएक्सप्शन' सेट करता है। पिंग() '।

एक बार जब मैं 'पिंग.स्टार्ट()' कहता हूं, तो मैं तुरंत बूलियन विधि पिंग का उपयोग करता हूं। थॉइन (टाइमस्पेन) धागे को सफलतापूर्वक वापस आने के लिए प्रतीक्षा करने के लिए, या अगर थ्रेड निर्दिष्ट राशि के भीतर वापस नहीं आता है तो आगे बढ़ें समय की। हालांकि, अगर धागा निष्पादित हो गया लेकिन अपवाद फेंक दिया गया, तो हम अभी भी पिंग को सच नहीं करना चाहते क्योंकि रिमोट ऑब्जेक्ट से संचार करने में कोई समस्या थी। यही कारण है कि मैं यह सुनिश्चित करने के लिए 'पिंगएक्सप्शन' का उपयोग करता हूं कि svr.Ping() को कॉल करते समय कोई अपवाद नहीं हुआ। यदि 'पिंगएक्सप्शन' अंत में शून्य है, तो मुझे पता है कि मैं सच होने के लिए सुरक्षित हूं।

ओह और आपके द्वारा मूल रूप से पूछे गए प्रश्न का उत्तर देने के लिए (.... कभी-कभी यह प्रक्रिया के दौरान NegotiateStream.ProcessRead नामक विधि पर अवरुद्ध करता है, और मुझे समझ में नहीं आता क्यों ...), मैं कभी भी सक्षम नहीं हुआ टाइमआउट मुद्दों को समझें।नेट रीमोटिंग, इसलिए यह तरीका है जिसे मैंने बेक किया है और हमारे .NET Remoting जरूरतों के लिए साफ़ किया है।

+0

मैंने थोड़ी देर में स्टैक ओवरफ़्लो की जांच नहीं की थी, और मेरी परियोजना पहले ही समाप्त हो चुकी है इसलिए मैं आपके समाधान का प्रयास नहीं करूंगा ... लेकिन यह सबसे पूर्ण और अच्छी तरह से समझाया गया उत्तर था, इसलिए मैं इसे स्वीकार्य मानूंगा! –

0

मैं जेनरिक के साथ इस का एक उन्नत संस्करण का उपयोग किया है:

internal static TResult GetRemoteProperty<T, TResult>(string Url, System.Linq.Expressions.Expression<Func<T, TResult>> expr) 
    { 
     T remoteObject = GetRemoteObject<T>(Url); 
     System.Exception remoteException = null; 
     TimeSpan timeout = TimeSpan.FromSeconds(5); 
     System.Threading.Tasks.Task<TResult> t = new System.Threading.Tasks.Task<TResult>(() => 
     { 
      try 
      { 
       if (expr.Body is System.Linq.Expressions.MemberExpression) 
       { 
        System.Reflection.MemberInfo memberInfo = ((System.Linq.Expressions.MemberExpression)expr.Body).Member; 
        System.Reflection.PropertyInfo propInfo = memberInfo as System.Reflection.PropertyInfo; 
        if (propInfo != null) 
         return (TResult)propInfo.GetValue(remoteObject, null); 
       } 
      } 
      catch (Exception ex) 
      { 
       remoteException = ex; 
      } 
      return default(TResult); 
     }); 
     t.Start(); 
     if (t.Wait(timeout)) 
      return t.Result; 
     throw new NotSupportedException(); 
    } 

    internal static T GetRemoteObject<T>(string Url) 
    { 
     return (T)Activator.GetObject(typeof(T), Url); 
    } 
संबंधित मुद्दे