【问题标题】:How to destroy QProcess when it finishes and the class than contaed the slot如何在 QProcess 完成时销毁它并且类比包含插槽
【发布时间】:2023-07-07 19:39:02
【问题描述】:

我在类的成员函数中启动了QProcess,但该对象(下面的 Pdf 对象)在创建进程后很快就会被销毁。我显然希望在 QProcess 完成时可以使用和调用 slot 函数。我传递了QProcess 指针,所以当它完成时,它也会销毁它。但实际上它完成后并没有真正被销毁。

void PDf::createPDF()
{
PdfSymlink * pdfSymlink = new PdfSymlink( fileName, linkName, myProcess );

connect(myProcess, SIGNAL(finished(int)), pdfSymlink, SLOT(createPdfLink(int)) );

myProcess->start("sh",args); // args is defined now shown in code
} 

这是一个重复的代码,被多次调用我希望 QProcess 在完成时被销毁,同样 pdfSymlink 也应该被销毁。我该怎么做?

请注意,我的插槽确实被调用并且它完成了工作,但我想确保在此对象之后进行清理。

【问题讨论】:

    标签: c++ qt qprocess


    【解决方案1】:

    好吧,您似乎一直在跟踪进程对象。你可以像这样实现createPdfLink(int)

    void createPdfLink(int status)
    {
        if(status != 0)
        {
           // Do error handling
        }
        else
        {
           // regular code
        }
    
        myProcess->deleteLater();
        deleteLater();
    }
    

    假设myProcess 也被存储为myProcessPdfSymlink 对象中。它会导致进程在被 Qt 允许删除时立即被 Qt 删除(主要是为了防止随机崩溃),并在允许时导致类本身被删除。

    额外:

    作为更简洁的代码,最好将connect 函数包含在PdfSymlink 类的构造函数中:

    PdfSymlink::PdfSymlink(QString fileName, QString linkName, QProcess * myProcess)
    {
        this->myProcess = myProcess;
        connect(myProcess, SIGNAL(finished(int)), SLOT(createPdfLink(int)));
    
        // More initialization code
    }
    

    这具有保持代码相关性的额外好处,并使“接收者”参数可选,因为使用了重载的非静态成员函数connect(sender,signal,method)

    【讨论】:

    • 这不起作用,我猜deleteLater 没有像宣传的那样工作。它实际上在 QProcess 完成之前破坏了 QProcess 并显示错误消息 QProcess: Destroyed while process ("sh") is still running. 如果我删除 deleteLater 调用我的 QProcess 确实完成并生成输出。
    • 我回家后会尝试一些东西,也许“完成”并不是最好的使用信号。
    • 谢谢,我有一个可行的解决方案,我想我会发布它可能对其他人有所帮助,但如果您知道更好,请告诉我
    【解决方案2】:

    因此,如果有人遇到同样的问题,我会修复它,我必须将 deleteLater 作为插槽调用:

    void PDf::createPDF()
    {
            QProcess *myProcess= new QProcess();
    
            PdfSymlink * pdfSymlink = new PdfSymlink( fileName, linkName, myProcess ); // fileName and LinkName definition is omitted 
    
            connect(myProcess, SIGNAL(finished(int)), pdfSymlink, SLOT(createPdfLink(int))
    
            // Call deleteLater
            connect(myProcess, SIGNAL(finished(int)), myProcess, SLOT(deleteLater()) );
    
            myProcess->start("sh",args); // args is defined now shown in code
    } 
    

    【讨论】:

    • 所有阅读此解决方案的人。请注意 deleteLater(int) SLOT 不存在,因此实际上永远不会调用 deleteLater。这相当于没有第二个连接。可能这在终端上显示为“无法将 QProcess::finished(int) 连接到 QProcess::deleteLater(int),没有这样的插槽”