3

ASYNC_TIMERS が定義されているときに、この qt コードが Callback を呼び出さない理由を教えてください (つまり、m_timer.start は pthread から呼び出されますが、スロットは実行されません)。明らかに、ASYNC_TIMERS が定義されていないときに機能するため、pthread から呼び出されることに関係していますが、pthread から修正する方法を知りたいです。moveToThread()、exec()を呼び出すスレッド実行の呼び出しなど、ネットで見つけた多くのことを試しましたが、この問題はうまくいきませんでしたか?

乾杯

multitimer.h:

#pragma once

#ifndef MULTI_TIMER_H
#define MULTI_TIMER_H

#include <QThread>
#include <QTimer>
#include <QMutex>

#include <QMap>


#include <QMetaType>
#include <cassert>


class MultiTimer : public QThread
{
    Q_OBJECT

public:
    typedef void (*multiTimerCallback)(quint32 p_id);

private:
    QTimer m_timer;
    QMutex m_mutex;
    quint32 m_id;
    multiTimerCallback m_callback;
    void KillTimer(void);

public:
    // only TimerFactory is allowed to instantiate MultiTimer
    MultiTimer(quint32 p_id, multiTimerCallback p_callback);
    ~MultiTimer();
    enum TTimerType
    {
        TT_SingleShot,      ///< Timer fires only once
        TT_Repetitive       ///< Timer keeps firing repeatedly until stopped with KillTimer()
    };
    void SetTimer(quint32 p_delayInMilliseconds, MultiTimer::TTimerType timerType);

private slots:
    void Update(void);
};

#endif

タイマー.cpp:

#include <QtCore/QCoreApplication>
#include "multitimer.h"
#include <stdio.h>


//--------------------------------------------------------------------------------------------------

void MultiTimer::SetTimer(quint32 p_delayInMilliseconds, MultiTimer::TTimerType timerType)
{
    QMutexLocker locker(&m_mutex);

    m_timer.setSingleShot(TT_SingleShot == timerType ? true : false);
    m_timer.start(p_delayInMilliseconds);
    //QTimer::singleShot(p_delayInMilliseconds, this,SLOT(Update()));
}

void MultiTimer::KillTimer(void)
{
    QMutexLocker locker(&m_mutex);
    m_timer.stop();
}

void MultiTimer::Update(void)
{
    QMutexLocker locker(&m_mutex);

    if (NULL != m_callback)
        m_callback(m_id);
}

MultiTimer::MultiTimer(quint32 p_id, multiTimerCallback p_callback)
    : m_id(p_id)
    , m_callback(p_callback)
{
    bool isConnected = true;
    isConnected &= this->connect(&this->m_timer, SIGNAL(timeout()), this, SLOT(Update()), Qt::QueuedConnection);
    assert(isConnected);
    //this->start();
}

MultiTimer::~MultiTimer()
{
    KillTimer();
    wait();
}


//--------------------------------------------------------------------------------------------------
#define ASYNC_TIMERS
#define GLOBAL_TIMERS

void Callback(quint32 p_id)
{
    printf("Got timered by timer %d.\n", p_id);
}

MultiTimer *mt;
void StartTimers(void)
{
    #ifndef GLOBAL_TIMERS
    mt = new MultiTimer(1, Callback);
    #endif
    mt->SetTimer(1000, MultiTimer::TT_SingleShot);
}

#ifdef ASYNC_TIMERS
pthread_t AsyncTaskThread;
void *ProcessAsyncTasks(void */*ptr*/)
{
    StartTimers();
    return NULL;
}
#endif

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    #ifdef GLOBAL_TIMERS
    mt = new MultiTimer(1, Callback);
    #endif

    #ifdef ASYNC_TIMERS
    pthread_create(&AsyncTaskThread, NULL, &ProcessAsyncTasks, NULL);
    #else
    StartTimers();
    #endif

    return a.exec();
}
4

3 に答える 3

4

Threads と QObjectsには答えがあると思います。作成したスレッドとは別のスレッドでイベント駆動型オブジェクトを使用することはできません。

コードでGLOBAL_TIMERSが有効になっている場合MultiTimer、メイン スレッドで を作成しますが、別のスレッドで呼び出しますm_timer.start()

ドキュメントを引用します:

イベント ドリブン オブジェクトは、単一のスレッドでのみ使用できます。具体的には、これはタイマーメカニズムとネットワークモジュールに適用されます。たとえば、タイマーを開始したり、オブジェクトのスレッドではないスレッドでソケットを接続したりすることはできません。

だから、それをしないでください。(そして、あなたがそれをしている間、QThreadを使用してください。)

于 2011-05-18T05:09:48.693 に答える
1

新しいスレッドでシグナル/スロットを処理するには、QEventLoopが必要です。

QTimerはそれらが機能する必要があります。

void *ProcessAsyncTasks(void */*ptr*/)
{    
    QEventLoop loop;
    StartTimers();    
    loop.exec();
    return NULL; 
}

QThreadを使用してみませんか?

于 2011-05-18T05:03:44.930 に答える
0

m_timer オブジェクトと multitimer オブジェクトをメインの qt スレッドに戻し、タイマー開始シグナルを「適切に」発行すると、すべてが機能しているように見えます (以下を参照)。

おそらく、qthread で exec 呼び出しを行って、pthread から引き継ぎ、マルチタイマーと m_timer をそこに移動することもできますが、この方法は今のところ機能し、時間通りに「タイマー %d によってタイマーが設定されました。\n」という出力が得られます。必要に応じて pthread が停止した後でも。

ご意見をお寄せいただきありがとうございます。これを行うためのより良い方法や、私が見落としている大きな間違いがある場合は、知っておくとよいでしょうか? 乾杯

multitimer.h:

/**
    @file multitimer.h
    @brief Partial implementation of Windows-like SetTimer()/KillTimer() for Qt.

*/
#pragma once

#ifndef MULTI_TIMER_H
#define MULTI_TIMER_H

#include <QThread>
#include <QTimer>
#include <QMutex>

#include <QMap>


#include <QMetaType>
#include <cassert>


class MultiTimer : public QThread
{
    Q_OBJECT

public:
    typedef void (*multiTimerCallback)(quint32 p_id);

private:
    QTimer m_timer;
    QMutex m_mutex;
    quint32 m_id;
    multiTimerCallback m_callback;
    void KillTimer(void);

public:
    // only TimerFactory is allowed to instantiate MultiTimer
    MultiTimer(quint32 p_id, multiTimerCallback p_callback);
    ~MultiTimer();
    enum TTimerType
    {
        TT_SingleShot,      ///< Timer fires only once
        TT_Repetitive       ///< Timer keeps firing repeatedly until stopped with KillTimer()
    };
    void SetTimer(quint32 p_delayInMilliseconds, MultiTimer::TTimerType timerType);

private slots:
    void Update(void);

signals:
    void start_sig(int);
};

#endif    

タイマー.cpp:

#include <QtCore/QCoreApplication>
#include "multitimer.h"
#include <stdio.h>


//--------------------------------------------------------------------------------------------------

void MultiTimer::SetTimer(quint32 p_delayInMilliseconds, MultiTimer::TTimerType timerType)
{
    QMutexLocker locker(&m_mutex);
    m_timer.setSingleShot(TT_SingleShot == timerType ? true : false);
    connect(this, SIGNAL(start_sig(int)), &m_timer, SLOT(start(int)), Qt::QueuedConnection);
    //m_timer.start(p_delayInMilliseconds);
    emit start_sig(p_delayInMilliseconds);
    disconnect(this, SIGNAL(start_sig(int)), &m_timer, SLOT(start(int)));
}

void MultiTimer::KillTimer(void)
{
    QMutexLocker locker(&m_mutex);
    m_timer.stop();
}

void MultiTimer::Update(void)
{
    QMutexLocker locker(&m_mutex);

    if (NULL != m_callback)
        m_callback(m_id);
}

MultiTimer::MultiTimer(quint32 p_id, multiTimerCallback p_callback)
    : m_id(p_id)
    , m_callback(p_callback)
{
    bool isConnected = true;
    isConnected &= this->connect(&this->m_timer, SIGNAL(timeout()), this, SLOT(Update()), Qt::QueuedConnection);
    assert(isConnected);
    //this->start();

    moveToThread(qApp->thread());
    m_timer.moveToThread(qApp->thread());
}

MultiTimer::~MultiTimer()
{
    KillTimer();
    wait();
}


//--------------------------------------------------------------------------------------------------
#define ASYNC_TIMERS
#define xGLOBAL_TIMERS

void Callback(quint32 p_id)
{
    printf("Got timered by timer %d.\n", p_id);
}

MultiTimer *mt;
void StartTimers(void)
{
    #ifndef GLOBAL_TIMERS
    mt = new MultiTimer(1, Callback);
    #endif
    mt->SetTimer(2000, MultiTimer::TT_SingleShot);
}

#ifdef ASYNC_TIMERS
pthread_t AsyncTaskThread;
void *ProcessAsyncTasks(void */*ptr*/)
{
    StartTimers();
    return NULL;
}
#endif

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    #ifdef GLOBAL_TIMERS
    mt = new MultiTimer(1, Callback);
    #endif

    #ifdef ASYNC_TIMERS
    pthread_create(&AsyncTaskThread, NULL, &ProcessAsyncTasks, NULL);
    #else
    StartTimers();
    #endif

    return a.exec();
}
于 2011-05-23T00:39:00.453 に答える