2013-04-30 36 views
5
  • Hệ điều hành: Qt 4.8.2, Win 7

Vui lòng xem xét dòng chảy logic sau:sử dụng đúng cách QProcess

1. App started 
2. functionA() triggered 
3. the app periodically capture some images to external files 
4. end of functionA() 
5. the app create a video from captured images, using ffmpeg as external program 
6. [step 2 -> step 5] may be repeated. 
7. App quit 

Để đạt được dòng chảy, tôi sử dụng QProcess để bắt đầu chương trình bên ngoài để tôi tham gia các hình ảnh, nhưng tôi đã nhầm lẫn với mẫu sử dụng thích hợp của QProcess. (Tôi không quan tâm đến những thông điệp giao diện điều khiển của ffmpeg, tôi xác định sự thành công của bước 5 bằng cách kiểm tra nếu các tập tin video được tạo ra.)

Cố gắng 1

void MyWidget::createAVI() 
{ 
    checkAndDeleteAVI(); 
    process = new QProcess(this); // process_ defined as class member; 
    process->start("ffmpeg -f images2 ...."); 
    process->waitForFinished(-1); // (a) 
    // (b) 
} 

Tại (a), Tôi đọc tài liệu, cuộc gọi này có thể đóng băng GUI chính, vậy tôi có nên gọi từ QThread/QRunnable không?

Lúc (b), tôi có bỏ sót điều gì ở đây không? như khi tôi cố gắng đóng ứng dụng, (bước 7 trong luồng), ứng dụng gặp sự cố và tôi nghĩ rằng QProcess được sinh ra không được phát hành đúng cách.

Cố gắng 2

Tôi đã viết một lớp wrapper của QProcess như sau:

Launcher.h

class Launcher : public QObject 
{ 
    Q_OBJECT 
public: 
    /** constructor */ 
    explicit Launcher(QObject *parent = 0); 
    /** destructor */ 
    ~Launcher() { 
     if (started_ && process_->state() != QProcess::NotRunning) 
      process_->kill(); 
    } // end_dtor(Launcher) 
Q_SIGNALS: 
    void feedbackLog(QString log); 
public Q_SLOTS: 
    void launch(QString program, QStringList argList); 
private: 
    QProcess * process_; 
    bool started_; 
private Q_SLOTS: 
    void error(QProcess::ProcessError error); 
    void finished(int exitCode, QProcess::ExitStatus status); 
    void stateChanged(QProcess::ProcessState state); 
}; // end_class(Launcher) 

#endif // LAUNCHER_H 

Launcher.cpp

#include "launcher.h" 
#include <QCoreApplication> 
#include <QtDebug> 

Launcher::Launcher(QObject *parent) : QObject(parent), started_(false) 
{ 
    process_ = new QProcess(this); 
    connect(process_, 
      SIGNAL(error(QProcess::ProcessError)), 
      SLOT(error(QProcess::ProcessError))); 
    connect(process_, 
      SIGNAL(finished(int, QProcess::ExitStatus)), 
      SLOT(finished(int, QProcess::ExitStatus))); 
    connect(process_, 
      SIGNAL(stateChanged(QProcess::ProcessState)), 
      SLOT(stateChanged(QProcess::ProcessState))); 
} // end_ctor(ExternalLauncher) 

void Launcher::launch(QString program, QStringList argList) 
{ 
    started_ = true; 
    process_->start(program, argList); 
    process_->waitForFinished(-1); // (c) 
    Q_EMIT feedbackLog(process_->readAllStandardOutput()); 
    process_->close(); 
} // end Launcher::launch() 

void Launcher::error(QProcess::ProcessError error) 
{ 
    /* just feedback some text about the error */ 
} // end_slot(Launcher::error) 

void Launcher::finished(int exitCode, QProcess::ExitStatus status) 
{ 
    started_ = false; 
    /* feedback some text about finished */ 
} // end_slot (Launcher::finished) 

void Launcher::stateChanged(QProcess::ProcessState state) 
{ 
    qDebug() << "Luancher::stateChanged" << state; 
} 

Làm thế nào tôi sử dụng Trình khởi chạy:

void MyWidget::createAVI() 
{ 
    checkAndDeleteAVI(); 
    launcher_.launch("ffmpeg", "argsList"); // launcher_ defined as class member; 
} 

Vì vậy, tại (c), nó không cần thiết để waitForFinished()? (như tôi đọc một số thông tin mà tôi không nên trộn lên waitForXXX() và khung tín hiệu/khe cho QProcess)

Ngoài ra, có điều gì đó tôi đã bỏ lỡ cho lớp Launcher, vì tôi cũng gặp sự cố ứng dụng khi sử dụng phương pháp này.

Câu hỏi chính: Nói chung, khi nào cần gọi QProcess :: terminate()/QProcess :: kill() và khi nào để xóa đối tượng QProcess?

Cảm ơn

Trả lời

2

Bạn không cần phải waitForFinished(), bạn sẽ nhận được tín hiệu về nó, vậy tại sao phải chờ đợi? Thay vào đó, bạn có thể muốn waitForStarted() trong launch() để đảm bảo rằng quá trình đã bắt đầu thành công. Tất nhiên trong trường hợp này, bạn sẽ cần phải thay đổi cách bạn sử dụng Launcher của bạn - không phá hủy nó chỉ sau launch().

Bạn không cần phải terminate()/kill() quy trình nếu quá trình này kết thúc, chỉ khi bạn cần dừng quá sớm. Bạn có thể xóa nó khi bạn nhận được tín hiệu finished() hoặc error() sử dụng process_->deleteLater() (bạn không thể chỉ delete process_ khi bạn đang ở trong vùng) hoặc trong ~Launcher(), với điều kiện là nó sẽ không được gọi cho đến khi quá trình kết thúc.

Các vấn đề liên quan