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

时间:2015-07-05 14:20:41

标签: c++ multithreading stl interrupt

说我们有一个简单的异步调用,我们想在超时时终止/终止/消除

// 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库来杀死运行asyncrinusly的任务呢?

2 个答案:

答案 0 :(得分:0)

我认为不可能安全地从循环本身外部中断运行周期,因此STL不提供这样的功能。当然,人们可能会试图杀死正在运行的线程,但它可能导致资源泄漏并不安全。

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

答案 1 :(得分:0)

无法停止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("timeout");
    }

    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.