【问题标题】:How to use a process (QProcess) in a new thread (QThread)?如何在新线程(QThread)中使用进程(QProcess)?
【发布时间】:2012-04-09 09:24:34
【问题描述】:

我有以下代码:

 void Processmethod()
{

    QDialog *ProcessMessage = new QDialog;      
    Ui::DialogProcessMessage Dialog;            
    Dialog.setupUi(ProcessMessage);             
    ProcessMessage->setModal(true);
    ProcessMessage->setAttribute(Qt::WA_DeleteOnClose); 
    ProcessMessage->show();

    qApp->processEvents();

    processmethodONE();  
    processmethodTWO();
    processmethodTHREE();                  
}

void processmethodONE()
{
    QString ProcessCommand = "w8 " + blablubli";            

    Prozess.setWorkingDirectory(Path);         //QProcess "Prozess" is globaly defined  
    Prozess.setStandardOutputFile(Path);       //in my class

    QThread* thread = new QThread;
    Prozess.moveToThread(thread);
    Prozess.start(ProcessCommand);


while(!Prozess.waitForFinished(2000))
   {
       std::cerr << "Process running " << std::endl;
   }

QProcess::ExitStatus Status = Prozess.exitStatus(); 

if (Status == 0)
 {
   std::cout << "File created!" << std::endl;
 }
}

在此源代码中,我尝试在某些进程启动之前打开一个弹出对话框。问题是对话框不可点击,但在对话框上我想创建一个按钮来中止运行方法。如您所见,我尝试使用 QThread 在另一个线程中运行进程,但我仍然无法单击对话框。此外,如果我使用“application/x-executable”文件打开我的应用程序(GUI),则在激活上述方法时会丢失对话框内容。我该如何解决这些问题?我哪里错了?问候

【问题讨论】:

  • 我有几个问题... 1) 你怎么打电话给Processmethod()? 2) 为什么你觉得你需要创建一个 QThread 并将 QProcess 移入其中?还有,你为什么不启动新的 QThread? 3) 你是否为你所有的processmethodX() 使用这个全局QProcess?
  • 它不适合这个问题,但我建议你用 lowerCamelCase 编写变量名称。它的可读性非常快。不过我同意 jdi,需要更多信息才能回答。
  • 通常不需要在线程中运行 QProcess,因为它的 API 不会阻塞,除非您使用 waitForStarted/Finished 方法。
  • @FrankOsterfeld:我敢打赌,一旦 OP 为我们提供了我的问题的答案,很明显这里有额外的问题(你在线程中不需要 QProcess 是正确的)跨度>
  • 1) 当单击按钮时,我调用 Processmethod()。 2)我认为在另一个线程中运行该进程会使对话框可点击/可用。你是对的,我没有启动 QThread - 我的错 - 我是否必须创建一个连接方法并将线程连接到我定义进程的方法? 3.每个进程都有一个 QProcess - 再次使用相同的会更好吗?我很抱歉我的错误,但我在理解 QThread 方法时遇到了问题,可能是因为我的英语不够好。 @Frank:正如你现在所看到的,我使用 waitForFinished - 编辑了我的问题。

标签: c++ qt qthread qprocess qdialog


【解决方案1】:

虽然我仍然不完全理解您最近更新的代码示例,但我觉得这可能是您的问题:

while(!Prozess.waitForFinished(2000))
   {
       std::cerr << "Process running " << std::endl;
   }

在等待 Prozess 完成时,无论您在原始代码中真正调用它的哪个位置都会阻塞。

为每个实例使用一个全新的 QProcess 实例,并将它们的 finished() 信号连接到一个 SLOT,当它们完成时将被调用。不要手动轮询它们并阻止它们。这将使您完全摆脱 QThreads。

【讨论】:

  • 每个进程都有一个全局的,这意味着 one QProcess Prozess for processmethodONE();one QProcess Prozess2 for processmethodTWO();... 我需要 waitForFinished() 方法,因为进程需要一些时间,并且前一个进程总是需要完成在下一次开始之前。
  • 如果是这种情况,那么您必须采取不同的方法。您的示例表明所有进程都能够同时运行。如果您需要它们按顺序运行,则可以将一个的finished() 信号链接到下一个的start() 插槽,依此类推。
  • 或者,您可以简单地创建一个自定义 QThread,它使用同步的低级 c++ 系统调用来执行您的所有命令,因为 QProcess 不再是一个好处。然后只需使用 QThread finished() 信号来宣布整个事情已经完成。
  • 我现在尝试将第一个进程“Prozess”的 finish() 信号与第二个方法“processmethodTWO()”与connect(Prozess, SIGNAL(finished()),processmethodTWO(),(SLOT(start()))); 连接,但我收到错误“无效使用 void 表达式”。 -> 可能是菜鸟失败:)。
  • 是的菜鸟失败:-) 做SLOT(Procezz2.start()) 而不是processmethodTWO()。你正在做的是试图调用它。老实说,我什至不确定这种语法是否正确。我是蟒蛇人
【解决方案2】:
void processmethodONE()
{
   QThread* thread = new QThread;
   Prozess.moveToThread(thread);
   Prozess.start(ProcessComand);

在这里,您将 QProcess 移至另一个线程。但是然后你调用 start() 就可以了。这已经不是线程安全的了。

while(!Prozess.waitForFinished(2000))
{
   std::cerr << "Process running " << std::endl;
}

这会阻塞并使使用线程无用。此外,它不是线程安全的。

您不应该使用线程,而是:

  1. 移除 waitForFinished() 调用
  2. 将 QProcess 的 finished() 和 error() 信号连接到插槽,然后开始下一步,即 processMethodTWO。

我还建议不要重复使用 QProcess 对象,而只需为每个步骤创建一个新对象。

【讨论】:

  • 好的,我先试试这个。我已经为每个进程拥有了一个不同的 QProcess 对象 - 这就是我想在第一条评论中说明的内容。
  • 我现在尝试用 connect(Prozess, SIGNAL(finished()),processmethodTWO(), 将第一个进程“Prozess”的 finish() 信号与第二个方法“processmethodTWO()”连接起来(插槽(开始()))); ,但我收到错误“无效使用无效表达式”。 -> 可能是菜鸟失败:)。
  • 使用finished() 信号而不是阻止waitForFinished() 确实有帮助。 QML 端缓冲了所有发出的信号,这些信号导致 UI 无响应,直到 QProcess 最终完成。非常感谢基本但挽救生命的帖子,十年后仍然有效:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-02
  • 2021-12-31
  • 2021-07-27
  • 2011-08-05
  • 1970-01-01
相关资源
最近更新 更多