使用QT进行分叉

时间:2018-05-07 15:31:00

标签: qt fork

使用QtCreator为软件制作更高级的界面。 基本上有一组用于调整和输入的按钮,一个启动和停止作业 按钮,我的问题来自一个冻结显示的无限循环,所以我想出了使用fork(),以便循环必须与主程序竞争,而不是吃掉整个资源(没有多线程),但程序崩溃吐痰:

[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not
been called
[xcb] Aborting, sorry about that.
a.out: ../../src/xcb_io.c:274: poll_for_event: Assertion 
`!xcb_xlib_threads_sequence_lost' failed.

呼叫循环的功能被称为' ON',' OFF'应该退出分叉过程。

//in button 'ON' func
ps = fork();
if(getpid() == ps)
{
    while(1)
    {
        strcpy(word, charset(minlength, maxlength, N));
        ui->pass->setText(word);//operation on the display
        ....SNIP
    }
}

//In button 'OFF' func
if(getpid() == ps)
    exit(0);

我真的想知道启动一段时间(1)的正确方法是什么,并且能够在不使用QT冻结窗口的情况下中断,退出或返回,谢谢。

2 个答案:

答案 0 :(得分:1)

你可能在这里崩溃:

ui->pass->setText(word);//operation on the display  

与Qt一样,您无法直接从非UI线程更改UI。仅来自信号和插槽机制。

不冻结UI的正确方法显然是在另一个线程中计算冗长的操作。

您可以通过多种方式实现这一目标:

一个是通过对QObject类进行子类化来创建'工作对象'这将执行所有繁重的操作。只要需要对象,就可以创建新的QThread对象。并使用QObject::moveToThread方法将创建的对象移动到新线程。要控制您的工作对象,您应该从对象发送信号并通过信号槽机制调用它的插槽。如果你直接调用它们 - 它们将在调用者线程中执行(所以不要执行像worker-> startHeavyJob();在UI线程中执行的操作)。而是在UI中发出信号(发出sigStartHeavyStuff();)并将其连接到工作对象的插槽(slotDoHeavyStuff();)

如果你不想打扰这个(如果操作很小)   - 您可以使用QApplication::processEvents()处理UI事件循环中的事件,同时进入无限循环。

另一种方法是使用QtConcurrentRun框架在管理自身的单独线程中运行函数。线程从线程池中获取并由Qt管理。这种方法看起来像你想要做的事情。虽然您仍然只能通过信号和插槽访问UI对象。

答案 1 :(得分:1)

我看到所提出的代码中存在一个导致冻结的大问题:当你处于循环中时,你永远不会让Qt处理任何事情。您需要允许Qt运行它的事件循环。最简单的方法是在循环中使用QApplication::processEvents()

由于几个原因,我也不是while(1)循环的粉丝。第一个是它可以吃机器周期等待事情发生。我怀疑你真的需要尽可能快地运行代码,你可能会在你的循环中躲开一些。

另一个问题是很难爆发。一种更清洁的方法就是这样的

void MyClass::on_pushButton_ON_clicked()
{
    MyClass::done = false;  // this is a class attribute
    while (!MyClass::done) {
        QApplication::processEvents();
        //...
    }
}

void MyClass::on_pushButton_OFF_clicked()
{
    MyClass::done = true;
}