如何在c++中阻止函数从外部运行

How to stop a function from running from outside in c++

本文关键字:函数 从外部 运行 c++      更新时间:2023-10-16

我想运行一个函数,如果函数在n毫秒后没有完成,则停止该函数并启动另一个函数。像这样的代码:

void run()
{
    //do something that doesn't have while(1)
}

void main()
{
    run();
    if(runFunctionDidntFinishInSeconds(10)
    {
        endPrintFunction();
        backupPlan();
    }
    return 0;
}

我搜索了一下,发现boost::timed_join函数。下面是我的代码:

void run()
{
    int a;
    for (int i = 0; i < 2000; i++)
        cout << i << endl;
}

int main()
{
    boost::thread t = new boost::thread(&run);
    if (t.timed_join(boost::posix_time::microseconds(10000))){
        cout << "done" << endl;
    }
    else{
        cout << endl << "not done" << endl;
    }

    system("pause");
    return 0;
}

但是它不能阻止线程't'的运行。我去终止线程,但这不是一个好的选择。我想让a函数在我指定的时间完成。系统每16毫秒得到一次输入,我想对它做一个处理,如果处理时间超过13毫秒,就离开它,去做一个备份计划。我想把它从写处理方法的人那里抽象出来。所以在它上面放一个while循环会带来延迟。我该怎么办?至少我认为我需要的是能够重置处理线程来做它需要再次做的事情!

我想你是在找类似std::future的东西。

http://en.cppreference.com/w/cpp/thread/future/wait_for

可以在另一个线程中启动函数,然后等待函数返回或超时。

例如:

std::future< void > future = std::async( std::launch::async, print );
auto status = future.wait_for( std::chrono::seconds( 10 ) );
if ( status == std::future_status::deferred )
{
    std::cout << "deferredn";
}
else if ( status == std::future_status::timeout )
{
    std::cout << "timeoutn";
}
else if ( status == std::future_status::ready )
{
    std::cout << "ready!n";
}

但是,这不会导致分离的线程结束。为此,有必要在启动时包含一个标志,以便分离的线程可以自己清理并保存退出。

void run(const std::atomic_bool& cancelled)
{
    int a;
    for (int i = 0; i < 2000; i++)
    {
        cout << i << endl;
        if (cancelled)
            return;
    }
}
std::atomic_bool cancellation_token = false;
std::future< void > future = std::async( std::launch::async, 
                                         run,
                                         std::ref(cancellation_token) );
auto status = future.wait_for( std::chrono::seconds( 10 ) );
if ( status == std::future_status::deferred )
{
    std::cout << "deferredn";
}
else if ( status == std::future_status::timeout )
{
    std::cout << "timeoutn";
    cancellation_token = true;
}
else if ( status == std::future_status::ready )
{
    std::cout << "ready!n";
}

我想把它从编写处理方法的人那里抽象出来。

标准c++没有办法从函数调用图的外部强制中断函数的控制流(它调用的函数可以抛出,但是有人不能为他们抛出)。

特定于os的线程系统有终止线程的方法。然而,这可能使程序处于未定义状态,因为没有调用任何堆栈变量的析构函数。由于你在杀死它的过程中不知道它在哪里,所以你无法有效地清理它。即使是C程序也不能保证任意函数可以被终止;它必须是一个不动态分配内存或其他必须清理的资源。

您可以通过非常仔细地编写函数来弥补这一点。但是这要求编写这个函数的人非常仔细地编写。因此,不存在抽象,因为编写函数的人必须知道规则是什么,并且必须遵循这些规则。

所以唯一有效的解决方案需要合作。该函数必须以这样一种方式编写,即可以通过那些依赖于操作系统的特性安全地停止它,或者必须定期检查一些值并停止本身

这里有两个又3/4个方法。

第一个要求您想要停止的代码合作。它要么在运行时轮询某个变量,要么定期调用可能抛出异常以停止执行的函数。boost可中断线程遵循第二种模式。

第二种方法要求启动一个新进程,将数据编组到函数,并使用IPC获取回信息。如果函数没有及时返回,则终止子进程。

第三个"一半"包括用不同的语言重写代码,或者使用c++作为脚本语言。您在解释器中运行代码,解释器为您执行第一种或第二种解决方案。


现在,一个实际的替代方案(1/4解决方案)是确保函数是纯功能性的,在一个单独的线程中运行它,并带有半可靠的中止消息(如第一个),并且如果花费太长时间就丢弃它的返回值。这不是您想要的,但要简单得多。

有一种方法可以将原子用作信号量,但这会产生完全的内存屏障,从而降低性能,因为每次迭代都有load:

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
std::atomic<bool> printFinished { false };
std::atomic<bool> shouldPrintRun { true };
void print()
{
    while (shouldPrintRun.load() /* && your normal stop condition*/)
    {
        //work..
    }
    printFinished.store(true);
}

int main()
{
    std::thread t(print);
    std::this_thread::sleep_for(std::chrono::seconds(10));
    if (!printFinished.load())
    {
        shouldPrintRun.store(false);
        t.join();
        std::cout << "help!";
    }
    return 0;
}

如果你不想让在另一个线程上运行的函数检查它是否需要停止,那么终止该线程是only选项。

一个可能的解决方案是,你必须把这个冗长的函数变成小的&短增量函数,它将在每次调用时继续执行任务。下面可以在线程中运行的代码将执行与时间切片器类似的工作,并且可以随意终止。

void Process()
{       
    bool flag = true;
    while (running)
    {
        std::chrono::high_resolution_clock::time_point time1 = std::chrono::high_resolution_clock::now();
        std::chrono::milliseconds span(16);
        while ( (std::chrono::high_resolution_clock::now() - time1 ) < span)
        {
            flag ? incremental_function1() : incremental_function2();
            if (!running) return;
        }
        flag = (!flag);
    }
}