Я разрабатываю небольшую программу, цель которой — убедиться, что один из наших серверов запущен и работает. В некоторых случаях сервер не отвечает, и для перезапуска сервера необходимо запустить сценарий.
Сначала я запускаю новый поток, отвечающий за получение информации, к которому затем присоединяется основной поток на определенный промежуток времени. Затем я прерываю поток, чтобы отключиться, и, наконец, присоединяюсь к нему, чтобы оставить достаточно времени для выполнения блоков catch и finally.
Теоретически это должно работать отлично: если промежуток времени достаточно короткий, это действительно указывает на то, что сервер не работает (поскольку за короткий выделенный промежуток времени невозможно установить соединение). Но в некоторых случаях, когда сервер действительно не работает, программа просто продолжит выполнение, как если бы исключение 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 не действует. Это потому, что код был отключен на неуправляемый?
Я потерялся здесь, поэтому любая идея будет приветствоваться! Спасибо!