Не може да убие Qt нишка с CryptoPP FileSink, работещ в метода за изпълнение на нишка

Имам UI приложение в C++ и QT5.4, използвам CryptoPP 5.6.2 за криптиране на файлове. Попаднах на следния проблем:

  1. Когато се натисне бутонът Encrypt, се стартира нова нишка въз основа на този урок.

    // new thread
    CryptoWorkerThread = new QThread;
    this->worker = new CryptoWorker(fileName.c_str(), newFileName.c_str(), key, keyLength, iv);
    this->worker->moveToThread(CryptoWorkerThread);
    connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
    connect(CryptoWorkerThread, SIGNAL(started()), worker, SLOT(process()));
    connect(worker, SIGNAL(finished()), CryptoWorkerThread, SLOT(quit()));
    connect(worker, SIGNAL(finished()), this, SLOT(on_CryptoWorker_finished()));
    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(CryptoWorkerThread, SIGNAL(finished()), CryptoWorkerThread, SLOT(deleteLater()));
    CryptoWorkerThread->start();
    
  2. Съхранявам указател към нишката и работника в класа mainwindow (родител на бутона за шифроване и по този начин слота)

    Работническа класа:

    class CryptoWorker : public QObject {
        Q_OBJECT
    public:
        CryptoWorker(const char* sourceFileName, const char* destFileName, const byte * key, int keyLength, const byte * iv);
        ~CryptoWorker();
    
        const char* sourceFileName;
        const char* destFileName;
    
        public slots:
        void process();
    
    signals:
        void finished();
        void error(QString err);
    
    private:
        // add your variables here
        const byte* key;
        const byte* iv;
        int keyLength;
    };
    
    CryptoWorker::CryptoWorker(const char* sourceFileName, const char* destFileName, const byte * key, int keyLength, const byte * iv){
        this->sourceFileName = sourceFileName;
        this->destFileName = destFileName;
        this->key = key;
        this->keyLength = keyLength;
        this->iv = iv;
    }
    
    CryptoWorker::~CryptoWorker(){
    
    }
    
    void CryptoWorker::process(){
    
        CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor(key, keyLength, iv);
    
    
        CryptoPP::FileSource(sourceFileName, true,
            new CryptoPP::StreamTransformationFilter(
                encryptor,
                new CryptoPP::FileSink(destFileName),
                CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING
            ),
            true // StreamTransformationFilter
        ); // FileSource
    
        emit finished();
    
        return;
    }
    

Сега, когато нишката се изпълнява и криптирам файл A към файл B в движение, използвайки тази функция:

CryptoPP::FileSource(sourceFileName, true,
        new CryptoPP::StreamTransformationFilter(
            encryptor,
            new CryptoPP::FileSink(destFileName),
            CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING
        ),
        true // StreamTransformationFilter
); // FileSource

Но нишката е блокирана, докато файлът завърши кодирането и записването, което може да отнеме няколко минути. Нямам начин да убия нишката, тъй като няма къде да сложа isAlive() проверка.

Опитвам се да намеря решение, което ще ми позволи да използвам FileSource, FileSink (скоростта в сравнение с fstream или file или qfile е невероятна) и също така ще ми позволи да отменя операцията в даден момент.

Реших наблюдението на напредъка, като добавих друга нишка, която проверява размера на новосъздадения криптиран файл B, но би било страхотно да имам контрол върху байтовете, които се записват в даден момент (за да мога да проверя isAlive() и да увеличавам броячите на данни ).

В този момент съм заседнал и не мога да намеря решение. Моля помогнете.


person michnovka    schedule 29.04.2015    source източник
comment
Добър въпрос. @Yachoor намери решението за вас.   -  person jww    schedule 29.04.2015


Отговори (1)


Можете да опитате да предадете false на втория параметър (pumpAll) на FileSource конструктора и да вършите работата в цикъл на части, като използвате метода Pump - това трябва да позволи проверка на isAlive и увеличаване на броячите.

person yachoor    schedule 29.04.2015
comment
Ти ме изпревари. Бих добавил към Pump въз основа на размера на дисковия блок, като 4096 или 16K. - person jww; 29.04.2015