【问题标题】:How can I cancel a hung Task?如何取消挂起的任务?
【发布时间】:2016-04-07 15:00:02
【问题描述】:

我们有一个 Windows 服务,它调用第 3 方方法,如果最终用户配置不当,该方法可能会挂起,这很难事先测试。我们通过超时调用任务中的方法来处理这种风险:

private int? FooWithTimeout()
{
    var timeout = TimeSpan.FromMinutes(1);
    var task = Task.Run(Foo);

    if (!task.Wait(timeout))
    {
        Log("Foo timed out...");
        return null;
    }

    if (task.IsFaulted)
    {
        Log("Foo threw an exception...");
        return null;
    }

    return task.Result;
}

第 3 方方法永远阻塞等待来自无法响应的资源的输入。它支持以任何方式、形状或形式取消,也没有内置超时。我们担心的是,随着服务的运行,这些任务会继续阻塞并慢慢积累,最终会消耗大量资源。

这是一个有效的担忧吗?我们是否需要以某种方式中止/处置任务?如果是这样,正确的做法是什么?

附录:有问题的第 3 方是 Crystal Reports。当被要求打印到需要用户进行某种额外输入的打印机时,它会挂起(例如,Microsoft XPS Document Writer 会在您打印到文件时提示您保存文件的位置)。挂起,我的意思是它试图显示一个用户提示来获取额外的输入,但它在 Windows 服务中,所以没有人看到用户提示,它永远等待人类告诉它如何打印。我们允许最终用户配置服务尝试打印到哪台打印机,并且实际上没有任何方法可以判断给定的打印机是否需要额外的输入而不是尝试打印。

【问题讨论】:

  • 什么是Foo?阻塞线程的正常方法?如果您需要中止任务,这可能会有所帮助:stackoverflow.com/a/19311606/1657476
  • 您的问题基本上是“我依赖于执行不佳、随机挂起的第三方软件,我该怎么办?”在我看来,问题应该通过首先不这样做来解决。如果您的第三方在解决问题方面做得不好,请让他们修复他们糟糕的设计,或寻找替代方案。像杀死线程这样的危险解决方法似乎在过程中解决问题为时已晚。
  • 哦-常见!我做了很多显示一些 UI 提示的 dll。当然它需要最终修复,但我并不总是有时间做正确的解决方案。然后一切顺利——注册表黑客、临时文件、批处理等等。这不是一个“糟糕的设计”,只是一个需要修复的错误。当您的应用程序很复杂时,很难找到所有出现的 UI 提示。

标签: c# task-parallel-library


【解决方案1】:

我们担心的是,随着服务的运行,这些任务会继续阻塞并慢慢积累

这是一个合理的担忧。您可以通过在使用小堆栈的特殊线程池上启动这些任务来减少其后果。这样内存使用量就会减少。但这不是一个完整的修复。如果您的应用程序必须长时间运行(而不是打算使用几个小时的 GUI 应用程序),那么这种解决方案将被证明是不可接受的,因为最终应用程序将遭受资源耗尽。

.NET 无法终止不合作的线程。您需要在它们自己的进程中运行这些操作。然后,您可以安全地终止这些进程。

使用 AppDomain 也可能是安全的,但不太确定。当 AppDomain 和其中的线程被中止时,每个进程的状态可能会被破坏。此外,并非所有线程都可以中止。特别是 IO 操作。

使用单独的进程也不能保证终止不会导致状态损坏。但在实践中,大多数可破坏的状态都存在于内存中。进程终止可能会清除所有不一致的状态。

【讨论】:

  • iis 也使用了 thread.abort。 iis 运行数周或数月。
  • IIS 仅在明确定义的点为 current 线程使用 Thread.Abort。 Thread.Abort 被称为“邪恶”,它不能被使用。
【解决方案2】:

一种方法可能是创建单独的线程来监视任何新创建的窗口 - 如果创建了任何新窗口 - 线程将尝试强制关闭它们。

枚举窗口:

How to enumerate all windows belonging to a particular process using .NET?

并关闭不需要的窗口:

How to use WM_Close in C#?

可能行不通,只是一个建议... :-)

【讨论】:

    猜你喜欢
    • 2017-10-22
    • 1970-01-01
    • 2014-01-19
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 2019-12-31
    • 1970-01-01
    相关资源
    最近更新 更多