当服务器宕机时,我发现超时总是很慢(使用TcpChannel,在.NET Remoting中无法正确设置超时时间)。下面是我如何使用Ping函数的解决方法(对于您的需求来说可能有点复杂,因此我将解释一下重要部分):
[System.Diagnostics.DebuggerHidden]
internal static bool Ping<T>(T svr)
{
if (svr == null) return false;
System.Reflection.MethodInfo PingFunc = typeof(T).GetMethod("Ping");
if (PingFunc == null) return false;
TimeSpan timeout = TimeSpan.FromSeconds(5);
Exception pingexception = null;
System.Threading.Thread ping = new System.Threading.Thread(
delegate()
{
try
{
PingFunc.Invoke(svr, null);
}
catch (Exception ex)
{
pingexception = ex;
}
}
);
ping.Start();
if (ping.Join(timeout))
{
if (pingexception == null)
return true;
}
return false;
}
希望注释可以解释我在这里做什么,但我会给您整个函数的详细说明。如果您不感兴趣,请跳到我解释ping线程的部分。
DebuggerHidden属性
我设置了DebuggerHidder属性,因为在调试时,在ping线程中可能会不断抛出异常,而且这是预期的。如果需要调试此函数,很容易将其注释掉。
为什么要使用反射和泛型类型
'svr'参数应该是一个具有Ping函数的类型。在我的情况下,服务器上实现了几个不同的可远程接口,其中有一个共同的Ping函数。这样,我只需调用Ping(svr),而无需转换或指定类型(除非在本地实例化对象为'object')。基本上,这只是为了语法方便。
Ping线程
您可以使用任何逻辑来确定可接受的超时时间,在我的情况下,5秒很好。我创建一个值为5秒的TimeSpan 'timeout',一个Exception pingexception,并创建一个新线程,试图调用'svr.Ping()',并将'pingexception'设置为调用'svr.Ping()'时抛出的任何异常。
一旦我调用'ping.Start()',我立即使用布尔方法ping.Join(TimeSpan)等待线程成功返回,或者如果线程在指定的时间内没有返回,则继续执行。但是,如果线程执行完毕但抛出异常,我们仍然不希望Ping返回true,因为与远程对象通信时出现了问题。这就是我使用'pingexception'确保调用svr.Ping()时没有发生任何异常的原因。如果最后'pingexception'为空,那么我就知道我可以安全地返回true。
哦,为了回答您最初提出的问题(...有时它在调用NegotiateStream.ProcessRead的方法时会阻塞,我无法理解为什么...),我从未能够解决.NET Remoting的超时问题,所以这种方法是我为我们的.NET Remoting需求开发和清理的。