3

USB デバイスなどのシステム リソースからデータを受信するまでブロックするスレッドがあります。このモデルを選択したのは、データの量が変動する可能性があり、いつでもデータを受信できる可能性があるためです。アプリケーションを終了すると、「<strong>QThread: Destroyed while thread is still running」というメッセージが表示されます。これらのスレッドを閉じるにはどうすればよいですか?

次のような他の問題/解決策を見てきました。

最初の解決策では、フラグ (コードに含まれています) を使用しますが、スレッドはフラグ チェックに到達しません。2 番目の解決策は QWaitCondition を使用しますが、最初の解決策と同じように見えます。

以下のコードの簡素化されたバージョンを含めました。システム コールの WaitForSingleObject() は、私が実際に使用しているもの (GetOverlappedResult()) の代わりです。

#ifndef CONTROLLER_H
#define CONTROLLER_H

#include <QObject>
#include <QThread>
#include <QReadWriteLock>
#include <QDebug>

#ifdef Q_OS_WIN
    #include <windows.h>
#endif // Q_OS_WIN

#ifdef Q_OS_LINUX
    #include <unistd.h>
#endif // Q_OS_LINUX

////////////////////////////////////////////////
//
//  Worker Object
//
////////////////////////////////////////////////
class Worker : public QObject {
    Q_OBJECT

public:
    QReadWriteLock lock;
    bool running;

public slots:
    void loop() {
        qDebug() << "entering the loop";
        bool _running;
        forever {

            lock.lockForRead();
            _running = running;
            lock.unlock();

            if (!_running) return;

            qDebug() << "loop iteration";

            #ifdef Q_OS_WIN
                HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
                WaitForSingleObject(event, INFINITE);
            #endif // Q_OS_WIN

            #ifdef Q_OS_LINUX
                read(0, 0, 1);
            #endif // Q_OS_LINUX
        }
    }
};

////////////////////////////////////////////////
//
//  Controller
//
////////////////////////////////////////////////
class Controller {
public:
    Controller() {
        myWorker.connect(&myThread, SIGNAL(started()), &myWorker, SLOT(loop()));
        myWorker.moveToThread(&myThread);
        myThread.start();
    }

    ~Controller() {
        // Safely close threads

        myWorker.lock.lockForWrite();
        myWorker.running = false;
        myWorker.lock.unlock();

        myThread.quit();

        //myThread.wait();
        //myThread.exit();
        //myThread.terminate();
    }

private:
    QThread myThread;
    Worker myWorker;
};

#endif // CONTROLLER_H
4

1 に答える 1

-1

Linux の場合:

pthread_kill() でスレッドにシグナルを送信すると、失敗コード EINTR で read() が中断されました。sigaction() を使用してシグナルを登録し、スローされたシグナルは SIGUSR1 でした。

// Global scope
void nothing(int signum) {}

...

// Within the start of the thread
pthread_t myThreadID = pthread_self(); // Get the thread ID
struct sigaction action;
action.sa_flags = 0;
sigemptyset(&action.sa_mask);
action.sa_handler = nothing;
sigaction(SIGUSR1, &action, NULL);

...

// When it's time to close the thread
pthread_kill(myThreadID, SIGUSR1);

Windows の場合:

GetOverlappedResult() のブロックを解除するために、SetEvent() を使用して OVERLAPPED の hEvent を通知しました。

// Store a reference to the event
HANDLE myEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

...

// Within the start of the thread
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = myEvent;

...

// When it's time to close the thread
SetEvent(myEvent);
于 2012-11-30T12:14:23.730 に答える