【问题标题】:Thread executing remote connection won't abort执行远程连接的线程不会中止
【发布时间】:2012-10-12 00:04:56
【问题描述】:

我正在设计一个小程序,其目标是确保我们的一个服务器启动并运行。在某些情况下,服务器不会应答,必须启动脚本来重新启动服务器。

首先,我启动了一个负责获取信息的新线程,然后主线程将其加入一定的时间跨度。然后我中止线程以断开连接并最终加入它以留出足够的时间来执行 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 没有效果。是因为代码已被关闭为非托管吗?

我在这里迷路了,所以欢迎任何想法!谢谢!

【问题讨论】:

  • Thread.Abort 最好避免。在很多情况下调用可能会导致问题...请参阅文档:msdn.microsoft.com/en-us/library/ty8d3wta.aspx 如果可能,请向您的线程发出信号,表明该停止并让它优雅地完成。
  • 好吧,我希望我可以。但是如果异常不起作用,什么样的信号才能起作用呢?

标签: c# multithreading threadabortexception


【解决方案1】:

实际上,我认为不需要为您的场景使用单独的线程。您可以使用同步操作检查服务器可用性。用于检查服务器可用性的功能是否提供超时选项?如果是,那么超时选项应该足够了。如果函数在超时之前返回,则表示服务器在线,否则服务器已关闭。

如果检查服务器可用性的功能没有提供超时选项并且可能导致线程永远等待(或很长时间),那么您可以使用新线程。但是,如果 Thread.Join(Timeout) 方法返回 true 并且 _status 变量也为 true,那么您可以确定服务器在线。如果Thread.Join(Timeout) 返回 false 则表示服务器已关闭。

作为一种好的做法,您应该在处理 Abort 异常的 catch 块中使用 Thread.ResetAbort。否则,一旦 catch 块执行完毕,运行时将重新抛出 ThreadAbort 异常。

【讨论】:

  • 您好,感谢您的回答。我认为您是对的:但是我不确定它是否确实解决了我的问题,因为流氓线程将继续运行。但我想这不是System.Environment.Exit 无法处理的。无论如何,再次感谢,如果它可以帮助我解决问题,我会确保给你一个很好的复选标记。
猜你喜欢
  • 1970-01-01
  • 2015-05-29
  • 2016-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-03
  • 1970-01-01
  • 2018-07-14
相关资源
最近更新 更多