我正在设计一个小程序,其目的是确保我们的服务器之一已启动并运行。在某些情况下,服务器将不会应答,并且必须启动脚本才能重新启动服务器。
首先,我开始一个负责获取信息的新线程,然后由主线程连接一段时间。然后我中断线程断开连接并最终加入它以留出足够的时间来执行catch并最终阻塞。
理论上它应该工作得很好:如果时间跨度足够短,它确实表明服务器已关闭(因为在短的分配时间内无法建立连接)。但在某些情况下,当服务器真的关闭时,程序将继续执行,就好像ThreadAbortException没有效果一样。问题是,这些停机时间非常零星,因此我无法自行调试以查看无法正常工作的情况。
这是怎么回事:
这是主线程,调用工作线程。非常直截了当。
public void LaunchCommand()
{
Thread pingThread = new Thread(new ThreadStart(Ping));
pingThread.Start();
while (!pingThread.IsAlive);
pingThread.Join(new TimeSpan(0, 0, _maxTime));
pingThread.Abort(); // Time's up.
pingThread.Join(); // Make sure we complete everything before moving on
}
这是被叫线程:
private void Ping()
{
try
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
serviceType = Type.GetTypeFromProgID(serviceProgID, _server, true);
service = Activator.CreateInstance(serviceType);
_xmlResult = ApxServiceType.InvokeMember("ExecuteXML", BindingFlags.InvokeMethod, null, service, new string[] { _dataset, Command, string.Empty }) as string;
stopwatch.Stop();
_latency = stopwatch.Elapsed;
// Trivial validations to make sure _status is true, such as _xmlResult.Contains(certainSubString); and such
_status = true; // Everything seems to work fine if we could make up to here.
}
catch (ThreadAbortException)
{
Console.WriteLine("Server timeout :(");
return;
}
catch (Exception e)
{
Console.WriteLine("Server exception: " + e.Message);
return;
}
finally
{
if (!_status)
{
_latency = new TimeSpan(0, 0, _maxTime);
}
}
}
Commands,serviceProgID等变量已在其他地方声明,并且已知可以正常工作。我猜我的问题跨越了秒表声明/初始化之后的三行。首先,我必须说我从类似的应用程序复制粘贴这些行,但基本上它应该只从给定的命令获取结果。不幸的是,因为我无法在严峻的情况下进行调试,所以我不知道哪一行存在问题,但无论如何,似乎ThreadAbortException没有效果。是因为代码已关闭到不受管理?
我迷失在这里所以任何想法都会受到欢迎!谢谢!
答案 0 :(得分:1)
我实际上并不认为需要为您的场景使用单独的线程。您可以使用同步操作检查服务器可用性。用于检查服务器可用性的功能是否提供超时选项?如果是,则超时选项应该足够了。如果函数在超时之前返回,则表示服务器处于联机状态,否则服务器已关闭。
如果检查服务器可用性的功能不提供超时选项并且可能导致线程永远等待(或长时间),那么您可以使用新线程。但是,如果Thread.Join(Timeout)
方法返回true并且_status
变量也为真,那么您可以确定服务器处于联机状态。如果Thread.Join(Timeout)
返回false,则表示服务器已关闭。
作为一种好的做法,您应该在处理中止异常的catch块中使用Thread.ResetAbort
。否则,一旦catch块完成执行,运行时将重新抛出ThreadAbort异常。