2013-05-10 19 views
5

我正在開發一個具有被動複製的項目,其中服務器之間互相交換消息。每個服務器的位置都是衆所周知的其他服務器。在調用Activator.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), 「TCP://本地主機:」 +位置+ 「/服務器」);? – AngelCastillo 2013-05-10 23:27:09

+0

在這種情況下沒有問題,MyType實現IMyType接口。正如我所說,這在大多數情況下都有效,所以我不認爲這可能是問題所在! – 2013-05-11 13:08:30

回答

1

當服務器關閉時,對我而言,超時一直很慢(使用TcpChannel,它不會讓您在.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; 
    } 

希望的註釋解釋什麼,我在這裏做,但我會給你整個功能的細分。如果你不感興趣,可以跳到我解釋ping線程的地方。

DebuggerHidden屬性

我設置DebuggerHidder屬性,因爲在調試時,異常可以在這裏不斷地甩在了平線,和他們的預期。如果需要調試此功能,則很容易對此進行評論。

爲什麼我使用反射和泛型類型

的「SVR」參數預計將與一平一功能的類型。在我的情況下,我有一個共同的Ping函數在服務器上實現了幾個不同的遠程接口。通過這種方式,我可以調用Ping(svr)而不必強制轉換或指定類型(除非遠程對象在本地實例化爲「對象」)。基本上,這只是爲了語法方便。

的平螺紋

你可以使用你要確定可接受的超時任何邏輯,在我的情況下,5秒良好。我創建了TimeSpan'timeout',值爲5秒,Exception pingexception,並創建一個嘗試調用'svr.Ping()'的新線程,並將'pingexception'設置爲調用'svr時引發的任何異常。中國平安()」。

一旦我調用'ping.Start()',我立即使用布爾方法ping.Join(TimeSpan)等待線程成功返回,或者如果線程沒有返回指定的數量的時間。但是,如果線程完成執行但拋出異常,我們仍然不希望Ping返回true,因爲與遠程對象進行通信時出現問題。這就是爲什麼我使用'pingexception'來確保在調用svr.Ping()時沒有發生異常。如果'pingexception'最後爲空,那麼我知道我可以安全地返回true。

哦,並回答你最初問的問題(有時它會阻止一個名爲NegotiateStream.ProcessRead的過程中的方法,我不明白爲什麼...),我從來沒有能夠找出超時問題。NET Remoting,所以這個方法就是我爲.NET Remoting需求而烘焙和清理的。

+0

我有一段時間沒有檢查堆棧溢出,並且我的項目已經完成,所以我不會嘗試你的解決方案......但它是最完整和最好解釋的答案,所以我將它標記爲已接受! – 2013-11-19 18:47:36

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); 
    } 
相關問題