如何在超时时停止异步评估功能?

How to stop a async evaluating function on timeout?

假设我们有一个简单的异步调用,我们希望在超时时kill/terminate/eliminate

// future::wait_for
#include <iostream>       // std::cout
#include <future>         // std::async, std::future
#include <chrono>         // std::chrono::milliseconds

// a non-optimized way of checking for prime numbers:
bool is_prime (int x) {
  for (int i=2; i<x; ++i) if (x%i==0) return false;
  return true;
}

int main ()
{
  // call function asynchronously:
  std::future<bool> fut = std::async (is_prime,700020007); 

  // do something while waiting for function to set future:
  std::cout << "checking, please wait";
  std::chrono::milliseconds span (100);
  while (fut.wait_for(span)==std::future_status::timeout)
    std::cout << '.';

  bool x = fut.get();

  std::cout << "\n700020007 " << (x?"is":"is not") << " prime.\n";

  return 0;
}

我们想在第一次超时发生时立即杀死它。以后找不到方法了。

我能找到的最接近停止 运行 任务的方法是 std::packaged_task reset 方法,但它没有说明它是否可以中断 运行 任务。那么如何在不使用 boost 线程或其他非 stl 库的情况下 运行 asyncrinus 终止一项任务?

我认为从循环本身之外安全地中断 运行 循环是不可能的,所以 STL 不提供这样的功能。当然,可以尝试杀死 运行 线程,但这并不安全,可能会导致资源泄漏。

您可以在 is_prime 函数中检查超时,如果发生超时,则从中检查 return。或者您可以尝试将对 std::atomic<bool> 的引用传递给 is_prime 并在每次迭代时检查其值。然后,当超时发生时,您更改 main 中原子的值,因此 is_prime returns.

无法立即停止 std::async...但是,您可以这样做,传递 bool 来终止 is_prime 方法并抛出异常如果超时:

// future::wait_for
#include <iostream>       // std::cout
#include <future>         // std::async, std::future
#include <chrono>         // std::chrono::milliseconds  

// A non-optimized way of checking for prime numbers:
bool is_prime(int x, std::atomic_bool & run) {
    for (int i = 2; i < x && run; ++i)
    {
        if (x%i == 0) return false;
    }

    if (!run)
    {
        throw std::runtime_error("timed out!");
    }

    return true;
}

int main()
{
    // Call function asynchronously:
    std::atomic_bool run;
    run = true;
    std::future<bool> fut = std::async(is_prime, 700020007, std::ref(run));

    // Do something while waiting for function to set future:
    std::cout << "checking, please wait";
    std::chrono::milliseconds span(100);
    while (fut.wait_for(span) == std::future_status::timeout)
    {
        std::cout << '.';
        run = false;
    }

    try
    {
        bool x = fut.get();
        std::cout << "\n700020007 " << (x ? "is" : "is not") << " prime.\n";
    }
    catch (const std::runtime_error & ex)
    {
        // Handle timeout here
    }

    return 0;
}

为什么能够停止线程不好。

在任意点停止线程是危险的,会导致资源泄漏,其中资源是指针、文件和文件夹的句柄以及程序应该做的其他事情。

终止线程时,线程可能正在工作也可能不工作。无论它在做什么,它都不会完成,任何成功创建的变量都不会调用它们的析构函数,因为没有线程可以 运行 它们。

I have outlined some of the issues here.