Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何过早地停止长时间运行的函数?_C++_Multithreading_Qt_C++17 - Fatal编程技术网

C++ 如何过早地停止长时间运行的函数?

C++ 如何过早地停止长时间运行的函数?,c++,multithreading,qt,c++17,C++,Multithreading,Qt,C++17,我正在研究一种绘图算法。为此,我从主GUI线程中的DAQ板获取数据,然后将数据发送到要处理的工作线程,工作线程使用新的QImage发出信号,我在GUI中显示为绘图。问题在于函数,我们称之为generateImage(),计算并生成QImage需要很长时间(~50-70毫秒,取决于数据长度),在此期间可能会出现另一组数据,这将要求工作线程从头开始重新计算绘图。我希望generateImage()放弃计算,并在新数据到达时重新开始计算。我的方法是设置一个成员布尔变量,让我们调用它b_abort\u,

我正在研究一种绘图算法。为此,我从主GUI线程中的DAQ板获取数据,然后将数据发送到要处理的工作线程,工作线程使用新的
QImage
发出信号,我在GUI中显示为绘图。问题在于函数,我们称之为
generateImage()
,计算并生成
QImage
需要很长时间(~50-70毫秒,取决于数据长度),在此期间可能会出现另一组数据,这将要求工作线程从头开始重新计算绘图。我希望
generateImage()
放弃计算,并在新数据到达时重新开始计算。我的方法是设置一个成员布尔变量,让我们调用它
b_abort\u
,并检查它在
generateImage()
内部是否设置为true,如果设置为true,在
generateImage()
外部,它始终保持为true,我只在调用
generateImage()
之前将其设置为false

所有这些都发生在工作线程中,我将子类化
QObject
,并使用
moveToThread()
将其移动到工作线程

开始计算的函数:

void WorkerThread::startCalc()
{
    b_abort_ = false;
    generateImage();
    // if b_abort_ is set to true, generateImage() will return prematurely 
    if(b_abort_)
        emit calcFinished();
    else
        b_abort_ = true;
}
执行所有计算并生成图像的函数:

void WorkerThread::generateImage()
{
    /* Calculation of some parts */
    for(int ii = 0; ii < Rawdata.length(); ++ii) // Starting main time consuming loop
    { 
        if(b_abort_)
            return;
        /* Perform calculation for one data point from Rawdata */
    }

    // data calculation complete, now it's time to generate QImage
    // before that I check if b_abort_ is set to true
    if(b_abort_)
        return;

    for(int ii = 0; ii < CalculatedData.length(); ++ii) // plotting calculated data on QImage
    {
        if(b_abort_)
            return;
        /* plot one data point from CalculatedData vector */
    }

    // generation of QImage finished, time to send the signal
    emit renderedPlot(image); // image is a QImage object
}
当我在我的主GUI线程中使用这种方法时,
generateImage()
函数会阻止所有事件循环,我的GUI会冻结,这使我认为在单个线程(主GUI线程或工作线程)中一次只能运行一个函数,因此在线程的事件循环返回到处理其他函数之前,
b_abort\u
中的任何更改都不会应用。当使用
WorkerThread
时,很难验证它是否工作,有时它工作正常,而有时它会生成错误分配错误,看起来它不工作(尽管可能是因为完全不同的原因,我不确定)。我想问一下您的意见,这是过早停止长期计算的正确方法吗?有没有其他方法比我目前的方法更可靠

如何提前停止另一个线程中的长时间运行的函数

您是正确的,唯一明智的方法是定期检查长时间运行的线程是否应该提前停止

请注意,您正在检查的标志必须是原子的,或者受互斥锁保护,或者以某种方式同步。否则,工作线程检查变量并且永远看不到值的更改是完全合法的(不,您不能为此使用
volatile

。。。这让我觉得在单个线程(主GUI线程或工作线程)中,一次只能运行一个函数

是的,那正是一根线!它是一个单一的线性执行线程。它不能同时做两件事。同时做两件事是拥有多个线程的全部原因

这种方法应该是让一个工作线程等待工作完成,一个只发送异步消息的主线程(开始用这个数据生成一个映像,或者中断处理,然后用这个数据重新开始,或者诸如此类)

如果主线程调用一个应该在工作线程中执行的函数,那么,您已经故意开始在主线程中执行它,并且主线程在返回之前不会执行任何操作。就像其他函数一样


另一方面,您的设计有一个问题:如果一个图像不断被新数据中断,它可能永远无法完成生成


通常的解决方案是双缓冲:让工作线程完成当前映像的生成,而主线程为下一个映像积累数据。当工作人员完成一个图像时,可以将其传回主线程进行显示。然后,工作线程可以开始处理下一个更新,因此它将使用主线程为其准备的“脏”更新缓冲区。后续更新将再次添加到下一张图像的缓冲区(现在为空)。

这是否回答了您的问题@UlrichEckhardt不,我想要的是从调用它的同一个线程中停止一个长时间运行的函数,而不是从另一个线程中停止/终止线程。“在一个线程中[…]一次只能运行一个函数”——情况就是这样。我宁愿换一种说法:线程从一个地方执行代码。当然,这个位置可以在不同的函数之间移动,但不能同时在两个位置。这个线程已经在做一些事情了,所以不是真的。您可以使用POSIX信号/处理程序,但它不太便携(标准C++接口不充分,因为您需要<代码> pthRead Type < /Cube >和/或<代码> pthRead SigMase<代码>来实现这项工作。所有这些都不会自动处理Qt信号,因此您仍然会在主线程中执行一些代码来发送该信号。重要的部分不是哪个线程设置它(而是再次阅读下面关于“以某种方式同步”的答案),而是执行某个操作的线程无法设置它,反之亦然。一个线程可以在不同的事情之间交替,但不能同时做两件事。BTW:我不确定这是误会,但是如果你有一个C++ <代码> qTox< /Cord>或<代码> STD::线程< /Cord>对象某处,那不是线程!它更像是一个<代码> STD::fStuts是一个文件,它是一个C++对象,可以用来与线程交互,以防出现误会。好,我明白了,用主线程检查和改变<代码> B.ABORTHY< <代码>的值,然后修改代码< >工作线程内的函数将能够提前返回,对吗?关于双缓冲,它对我来说并不像大多数t
void WorkerThread::receiveData(QVector<double> data)
{
    if(!b_abort_) // check if calculation is still running
    { 
        QEventLoop loop;
        connect(this, &WorkerThread::calcFinished, &loop, &QEventLoop::quit);
        b_abort_ = true; // set it to true and wait for calculation to stop
        loop.exec();
        // start new calculation
        RawData = data;
        startClac();
    }
    else
    {
        RawData = data;
        startClac();
    }
}