C# 如何取消挂起的任务?

C# 如何取消挂起的任务?,c#,task-parallel-library,C#,Task Parallel Library,我们有一个Windows服务,它调用第三方方法,当最终用户配置不当时,该方法可能会挂起,这很难事先进行测试。我们通过在具有超时的任务中调用该方法来处理此风险: private int? FooWithTimeout() { var timeout = TimeSpan.FromMinutes(1); var task = Task.Run(Foo); if (!task.Wait(timeout)) { Log("Foo timed out...

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

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;
}
第三方方法阻止永远等待来自无法响应的资源的输入。它不以任何方式、形状或形式支持取消,也没有内置超时。我们担心的是,当服务运行时,这些任务将继续阻塞并缓慢累积,最终会消耗大量资源

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

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

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

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

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

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


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

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

枚举窗口:

并关闭非通缉窗口:


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

什么是
Foo
?阻止线程的常规方法?如果您需要中止某项任务,这可能会有所帮助:您的问题基本上是“我依赖于执行不善、随机挂起的第三方软件,我该怎么办?”在我看来,问题应该首先通过不这样做来解决。如果您的第三方在解决问题方面做得不好,那么让他们修复他们糟糕的设计,或者找到替代方案。危险的解决方法,比如杀死线程,似乎在这个过程中解决问题太晚了。哦,很常见!我已经做了很多dll,其中显示了一些UI提示。当然,它最终需要被修复,但我并不总是有时间去做正确的解决方案。然后一切都开始了——注册表黑客、临时文件、批处理等等。这不是一个“糟糕的设计”,只是一个需要修复的bug。当应用程序复杂时,很难找到所有出现的UI提示。iis也使用thread.abort。iis运行数周或数月。iis使用线程。仅在定义良好的点上为当前线程中止。已知Thread.Abort为“邪恶”,不能使用。