Передача пользовательского указателя класса в другой поток через механизм сигнала / слота в Qt - PullRequest
0 голосов
/ 23 апреля 2020

Я пытаюсь передать собственный указатель класса (с использованием полиморфизма) другому, используя механизм сигнальных слотов. В основном у меня есть базовый класс и несколько производных классов (они не расширены из QObject), и я пытаюсь передать базовый класс другому потоку, используя механизм сигнальных слотов, как описано в примере ниже. Когда я делаю это, я могу успешно передать указатель базового класса в другой поток, но когда я пытаюсь уменьшить его или вызвать виртуальный метод, я получаю исключение sigsegv. Я перебрал много статей, но не смог найти правильного решения, кто-нибудь сталкивался с такой проблемой раньше?

Это часть, которую я создал рабочие потоки

qRegisterMetaType<SecondMessage>();
for (const auto& receiver : glimpseReceivers) {
    QThread *thread = new QThread();
    receiver->moveToThread(thread);
    QObject::connect(thread, SIGNAL(started()), receiver.get(), SLOT(start()));
    QObject::connect(receiver.get(), SIGNAL(finished()), thread, SLOT (quit()));
    QObject::connect(receiver.get(), SIGNAL (finished()), receiver.get(), SLOT (deleteLater()));
    QObject::connect(thread, SIGNAL(finished()), thread, SLOT (deleteLater()));
    QObject::connect(receiver.get(),&MAGlimpseReceiver::sequenceNumberReceived,this,&MAItchManager::sequenceReceived);
    QObject::connect(receiver.get(),&MAGlimpseReceiver::glimpseDataSignal,this,&MAItchManager::itchDataReceived);
    thread->start();
    threadList.push_back(thread);
}

Это сигнал, который вызывается из рабочего потока в основной поток:

void MAGlimpseReceiver::glimpseDataReceived(ITradeMessagePtr tradeMessage) {
    if (tradeMessage != nullptr) {
        spdlog::debug("Glimpse Data Received For Market:{} Part:{} Type:{}",configuration.marketId,configuration.partId,tradeMessage->getType());
        emit glimpseDataSignal(tradeMessage.get(),int(configuration.marketId),configuration.partId);
    }
}

Это слот в главном потоке, который получает сигнал и попробуйте использовать виртуальный метод

void MAItchManager::itchDataReceived(ITradeMessage* tradeMessage,int marketId,int partId) {
    spdlog::debug("Itch Data Received for Market: {} Part: {} Type:{}",marketId,partId,char(tradeMessage->getType()));
    if (tradeMessage->isValidMessage()) {
        auto itchPackage = std::make_shared<ItchPackage>();
        ItchMessage *itchMessage = tradeMessage->getItchMessage();
        itchPackage->market = MarketType (marketId);
        itchPackage->part = partId;
        itchPackage->itchMessage = itchMessage;
        if (callBack != nullptr) {
            callBack(itchPackage.get());
        }
    } else {
        spdlog::error("Unknown Trade Message Type:{}",tradeMessage->getType());
    }
}

И это один из примеров базовых и производных классов, которые я пытаюсь перенести в основной поток. Базовый класс:

class ITradeMessage {
public:

    ITradeMessage() {

    }

    ITradeMessage(const char* message) {

    }

    virtual ~ITradeMessage() {
    }

    ItchMessageType getType() const {
        return type;
    }

    virtual ItchMessage * getItchMessage() = 0;

    bool isValidMessage() const {
        return validMessage;
    }

protected:
    ItchMessageType type = ItchMessageType::Msg_None;
    bool validMessage = false;
};

using ITradeMessagePtr = std::shared_ptr<ITradeMessage>;

Производный класс:

class SecondMessage: public ITradeMessage {
public:
    SecondMessage() = default;
    SecondMessage(const char* message);
    SecondMessage(const SecondMessage& obj);
    ~SecondMessage() = default;

    friend std::ostream& operator<<(std::ostream&, const SecondMessage&);
    ItchMessage *getItchMessage();
};
Q_DECLARE_METATYPE(SecondMessage); //Compiler gives this warning but still compiles: Excess elements in struct initializer
using SecondMessagePtr = std::shared_ptr<SecondMessage>;

1 Ответ

0 голосов
/ 29 апреля 2020

Я нашел решение, спасибо @ GM

Нам нужно точно указать тип, как мы собираемся его использовать, например:

qRegisterMetaType<std::shared_ptr<ITradeMessage>>()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...