【问题标题】:Is there a way to cancel non-cancellable C# task without waiting the timeout if the task finishes earlier?如果任务提前完成,有没有办法取消不可取消的 C# 任务而不等待超时?
【发布时间】:2016-03-11 02:05:34
【问题描述】:

我有一个我无法控制的方法(假设它来自另一个库):

private static void DoWork()
{
    // I have no control over this method
    while (true)
    {
        Console.WriteLine("Still working");
    }
}

我想等待一段时间(例如 20 秒),如果在这段时间内作业没有完成,则停止代码。

到目前为止我已经尝试过:

  • 使用任务取消模式对我来说不是一个选项,因为我无法控制我正在执行的方法

  • 仅使用 Task 类不是一个选项,因为不使用取消令牌我无法停止任务的执行

    var taskToWaitAndKill =
        Task.Factory.StartNew(DoWork);
    taskToWaitAndKill.Wait(20000); // 20 seconds
    // The task cannot be stopped (aborted) and still runs...
    
  • 使用 Thread 类,等待它并中止它不是一个选项,因为我需要等待所有 20 秒才能停止代码。

    var thread = new Thread(DoWork);
    thread.Start();
    Thread.Sleep(20000);
    thread.Abort();
    

所以我的问题有没有办法在 C# 中等待固定的毫秒数让代码执行,如果代码更早完成则不再等待?

【问题讨论】:

  • 必须中止操作吗?还是可以在您恢复工作时在后台继续运行?
  • 请参阅if this answer 帮助。

标签: c# .net multithreading task cancellation


【解决方案1】:

使用 Thread 类,等待它并中止它不是一个选项,因为我需要等待所有 20 秒才能停止代码。

换一种方式,你就可以做到:

var timeout = TimeSpan.FromSeconds(20);
var started = DateTime.UtcNow;
var thread = new Thread(DoWork);
thread.Start();
while (thread.IsAlive && DateTime.UtcNow - started < timeout)
{
    Thread.Sleep(10);
    // Do whatever here
}

// timeout occured, aborting
if (thread.IsAlive)
    thread.Abort();

但是,Abort 杀死线程是dangerous operation,可能会引起意外。如果您确实必须执行您无法控制的外来代码(例如 3rd 方插件),那么您应该为它们创建一个AppDomain。如果出现任何错误(包括ThreadAbortException),您可以安全地卸载AppDomain

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-04
    • 2019-12-17
    • 1970-01-01
    • 2014-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多