2013-05-10 45 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 

+0

あなたはIMyTypeレプリカ= IMyType)Activator.GetObject(typeof演算(IMyType)、もしかして "TCPを:// localhostを:" +場所+ "/サーバ");? – AngelCastillo

+0

この場合、MyTypeはIMyTypeインターフェイスを実装しても問題ありません。そして、私が言ったように、これはほとんどの時間で動作するので、私はそれが問題になるとは思わない! –

答えて

1
...私はこれを行うと、それは(遅いですが)ほとんどの時間を動作しますが、処理中に NegotiateStream.ProcessReadと呼ばれる方法で、時にはそれブロック、私は理由を理解することはできません

サーバーがダウンしている場合、タイムアウトは常に低速です(TcpChannelを使用すると、.NET Remotingでタイムアウトを適切に設定できません)。以下は、私は私のPingの機能を使用する方法のための回避策は、(それはおそらくあなたのニーズに合わせて少し複雑ですので、私はあなたには関係の部品を説明します)です:

[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スレッドについて説明するところまでスキップしてください。デバッグ時に、例外がpingスレッドで常にここにスローされる可能性があり、それらが期待されているので、

DebuggerHidden属性

私はDebuggerHidder属性を設定します。この関数をデバッグする必要がある場合は、これをコメントアウトするだけでも簡単です。

は、なぜ私は反射と「SVR」パラメータがPingの機能を持つタイプであることが期待されるジェネリック型

を使用しています。私の場合は、一般的なPing機能を使用して、サーバー上に実装されたいくつかの異なるリモートインタフェースがあります。このようにして、型をキャストまたは指定することなくPing(svr)を呼び出すことができます(リモートオブジェクトが 'オブジェクト'としてローカルにインスタンス化されていない限り)。基本的には、構文上の便宜のためです。あなたは、私の場合には、あなたが許容タイムアウトを決定するために好きなロジック5秒を使用することができます

pingのスレッド

が良いです。私は5秒の値、例外pingexception、および 'svr.Ping()'を呼び出しようとするTimeSpanのタイムアウトを作成し、 'svrを呼び出すときにスローされたものに' pingexception 'を設定します。 Ping() '

私は 'ping.Start()'を呼び出すとすぐにブールメソッドping.Join(TimeSpan)を使用してスレッドが正常に戻るのを待つか、スレッドが指定された量時間の。しかし、スレッドが実行を終了したが例外がスローされた場合、リモートオブジェクトとの通信に問題があったため、Pingがtrueを返すことはありません。このため、私はsvr.Ping()を呼び出すときに例外が発生していないことを確認するために 'pingexception'を使用しています。最後に 'pingexception'がnullの場合、私は真実を返すのが安全だと知っています。

ああ、もともと尋ねた質問に答えるには(時には、プロセス中にNegotiateStream.ProcessReadというメソッドをブロックしますが、なぜ理解できないのですか...)、私は決してできませんでしたタイムアウトの問題を理解してください。NET Remotingを使用しているので、このメソッドは私が焼き付けて.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); 
    } 
関連する問題