在调用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
,我不明白为什么...
当服务器关闭时,对我而言,超时一直很慢(使用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需求而烘焙和清理的。
我有一段时间没有检查堆栈溢出,并且我的项目已经完成,所以我不会尝试你的解决方案......但它是最完整和最好解释的答案,所以我将它标记为已接受! – 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);
}
您的意思是IMyType副本= IMyType)Activator.GetObject(typeof运算(IMyType), “TCP://本地主机:” +位置+ “/服务器”);? – AngelCastillo 2013-05-10 23:27:09
在这种情况下没有问题,MyType实现IMyType接口。正如我所说,这在大多数情况下都有效,所以我不认为这可能是问题所在! – 2013-05-11 13:08:30