在调用Activator.GetObject后检查对象是否存在

问题描述:

我正在开发一个具有被动复制的项目,其中服务器之间互相交换消息。每个服务器的位置都是众所周知的其他服务器。在调用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

当服务器关闭时,对我而言,超时一直很慢(使用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

我用了这样的一个改进版本与仿制药:

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); 
    }