当服务器关闭时,超时对我来说总是很慢(使用 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 线程的地方。
DebuggerHidden 属性
我设置了DebuggerHidder属性是因为在调试的时候,ping线程中会不断的抛出异常,这是意料之中的。如果需要调试此功能,很容易将其注释掉。
为什么我使用反射和泛型类型
'svr' 参数应为具有 Ping 功能的类型。在我的例子中,我在服务器上实现了几个不同的远程接口,具有一个通用的 Ping 功能。通过这种方式,我可以只调用 Ping(svr) 而无需强制转换或指定类型(除非远程对象在本地实例化为“对象”)。基本上,这只是为了语法方便。
Ping 线程
您可以使用任何您想要确定可接受的超时的逻辑,在我的情况下,5 秒是好的。我创建了一个值为 5 秒的 TimeSpan 'timeout',一个异常 pingexception,并创建了一个尝试调用 'svr.Ping()' 的新线程,并将 'pingexception' 设置为调用 'svr.平()'。
一旦我调用 'ping.Start()',我立即使用布尔方法 ping.Join(TimeSpan) 等待线程成功返回,或者如果线程在指定时间内没有返回,则继续。但是,如果线程完成执行但抛出异常,我们仍然不希望 Ping 返回 true,因为与远程对象通信时出现问题。这就是为什么我使用 'pingexception' 来确保调用 svr.Ping() 时没有发生异常。如果'pingexception'最后为null,那么我知道我可以安全地返回true。
哦,要回答您最初提出的问题(....有时它会在此过程中阻塞一个名为 NegotiateStream.ProcessRead 的方法,我不明白为什么...),我一直无法弄清楚超时.NET Remoting 的问题,所以这个方法是我为我们的 .NET Remoting 需要烘焙和清理的。