I'm trying to call a method of another thread (not the Main), using invokeMethod. Unfortunately that makes the application crash as soon as it tries to execute the invokeMethod!
Am I mistaking something?
// main.cpp
#include <QtCore>
#include "entrypointclass.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << a.thread()->currentThreadId() << " - Application started.";
EntryPointClass entryPoint;
entryPoint.runInNewThread();
return a.exec();
}
// Entrypoint.h
#ifndef ENTRYPOINTCLASS_H
#define ENTRYPOINTCLASS_H
#include "worker.h"
#include <QtCore>
class EntryPointClass : public QObject
{
Q_OBJECT
public:
EntryPointClass();
~EntryPointClass();
void runInNewThread();
public slots:
void timeoutExpired();
private:
Worker* m_Worker;
QThread* m_Thread;
};
#endif // ENTRYPOINTCLASS_H
// Entrypoint.cpp
#include <QTCore>
#include "entrypointclass.h"
#include "Worker.h"
EntryPointClass::EntryPointClass()
{
qDebug() << "EntryPointClass created";
}
EntryPointClass::~EntryPointClass()
{
qDebug() << "EntryPointClass destroyed";
}
void EntryPointClass::runInNewThread()
{
QThread* m_Thread = new QThread;
Worker* m_Worker = new Worker();
connect(m_Thread, SIGNAL(started()), m_Worker, SLOT(doSomething()));
connect(m_Worker, SIGNAL(finished()), m_Thread, SLOT(quit()));
connect(m_Thread, SIGNAL(finished()), m_Thread, SLOT(deleteLater()));
connect(m_Thread, SIGNAL(finished()), m_Worker, SLOT(deleteLater()));
QTimer* timer = new QTimer;
timer->setSingleShot(true);
//bool bOK = connect(timer, SIGNAL(timeout()), m_Worker, SLOT(closeWorker()), Qt::BlockingQueuedConnection);
connect(timer, SIGNAL(timeout()), this, SLOT(timeoutExpired()));
m_Worker->moveToThread(m_Thread);
m_Thread->start();
timer->start(5000);
}
void EntryPointClass::timeoutExpired()
{
qDebug() << "timeout expired";
if (m_Worker != NULL)
{
QMetaObject::invokeMethod(m_Worker, "closeWorker", Qt::QueuedConnection);
}
}
// Worker.h
#ifndef WORKER_H
#define WORKER_H
#include <QtCore>
class Worker : public QObject
{
Q_OBJECT
public:
Worker();
~Worker();
public slots:
void doSomething();
void closeWorker();
private:
bool m_bAbort;
QMutex m_mutex;
signals:
void finished();
};
#endif // WORKER_H
// Worker.cpp
#include "worker.h"
#include <unistd.h>
#include "QTcore"
Worker::Worker()
: m_mutex()
{
qDebug() << this->thread()->currentThreadId() << "Worker created";
m_bAbort = false;
//qDebug() << QString("Thread %1 - Worker created").arg("");//this->thread()->currentThreadId());
}
Worker::~Worker()
{
qDebug() << this->thread()->currentThreadId() << "Worker destroyed";
}
void Worker::doSomething()
{
while(!m_bAbort)
{
sleep(2);
qDebug() << this->thread()->currentThreadId() << "Do Something!";
}
emit finished();
}
void Worker::closeWorker()
{
qDebug() << this->thread()->currentThreadId() << "closeWorker triggered!";
QMutexLocker mutexLocker(&m_mutex);
m_bAbort = true;
}
Instead of invoking a method directly, try posting a custom event. This will require that you implement an event filter at the target that handles your custom event. Event posting always works as long as an event loop is active in the target thread.
Take a look at this answer here too. Also here.
Hope this helps.
Related
//Work.h
#ifndef WORK_H
#define WORK_H
#include <QDebug>
#include <QObject>
#include <QThread>
class Work : public QObject {
Q_OBJECT
public:
explicit Work(QObject *parent = nullptr);
public slots:
void snap();
void setStatus();
signals:
private:
bool status;
};
#endif // WORK_H
//Work.cpp
#include "Work.h"
Work::Work(QObject *parent) : QObject(parent) { status = true; }
void Work::snap() {
status = true;
while (true) {
if (status) {
qDebug() << "Work thread: " << QThread::currentThreadId();
} else {
qDebug() << "STOP";
break;
}
}
}
void Work::setStatus() { status = false; }
//MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QThread>
#include "Work.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
Work *work;
QThread thread;
};
#endif // MAINWINDOW_H
//MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
work = new Work();
work->moveToThread(&thread);
thread.start();
connect(ui->startButton, SIGNAL(clicked()), work, SLOT(snap()));
connect(ui->stopButton, SIGNAL(clicked()), work, SLOT(setStatus()));
}
MainWindow::~MainWindow() {
thread.terminate();
delete ui;
}
//main.cpp
#include <QApplication>
#include "MainWindow.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
qDebug() << QThread::currentThreadId();
w.show();
return a.exec();
}
I use MainWindow to display, Work to do something. And I use work->moveToThread(&thread).
Click start button to execute snap function in Work, what I want to do is when I click stop button, the snap function output STOP. And I can still start and stop whenever I like.
But I fail. It seems impossible to change the status during the while loop. Work doesn't get the stopButton clicked signal. Is it because of priority?
Could anyone give me some advices?
Firstly consider your Work::snap implementation...
void Work::snap() {
status = true;
while (true) {
if (status) {
qDebug() << "Work thread: " << QThread::currentThreadId();
} else {
qDebug() << "STOP";
break;
}
}
}
Once started it never yields control to the Qt event loop. Now consider the connect call...
connect(ui->stopButton, SIGNAL(clicked()), work, SLOT(setStatus()));
Since ui->stopButton and work have different thread affinities this is effectively a queued connection and requires the receiver to have an active event loop. Hence the call to setStatus will remain pending forever.
A better way to achieve your goal might be to make use of a simple atomic bool...
std::atomic<bool> status;
and change the connect call to modify status directly using a lambda (untested)...
connect(ui->stopButton, &QPushButton::clicked, [this]{ work->setStatus(); });
I solve it.
I add a slot and a signal in MainWindow and change stop slot.
connect(ui->startButton, &QPushButton::clicked, this, &MainWindow::start);
connect(this, &MainWindow::startSnap, work, &Work::snap);
// start slot
void MainWindow::start() {
thread.start();
emit startSnap();
}
void MainWindow::stop() {
if (thread.isRunning()) {
thread.requestInterruption();
}
}
And change the codes in Work::snap
void Work::snap() {
while (true) {
if (QThread::currentThread()->isInterruptionRequested()) {
qDebug() << "STOP";
QThread::currentThread()->exit();
return;
} else {
qDebug() << "Work thread: " << QThread::currentThreadId();
}
}
}
The key codes are:
thread.requestInterruption();(MainWindow::stop)
QThread::currentThread()->exit();(Work::snap)
thread.start();(MainWindow::start)
I have a class that creates a server with multithreading. With the help of multithreading, I can connect several users at the same time. In one stream, the QByteArray Data is written, but I need this variable in the lane or in the lane heder, so that I can output this line (i.e., QByteArray Data). How I can tranfer var Data in my main function or header main?
I want write Data in QLable or somthing...
main.c
#include "groundstation.h"
#include <QApplication>
#include "server.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GroundStation w;
Server wServer;
wServer.StartServer();
//qDebug() << ServerThread::getString();
// QLabel *label = new QLabel();
//label->setText((QString));
w.show();
return a.exec();
}
server.cpp
#include "server.h"
Server::Server(QObject *parent) :
QTcpServer (parent)
{
}
void Server::StartServer(){
if(!this->listen(QHostAddress::Any, 1234)){
qDebug() << "Could not start server";
}
else {
qDebug() << "Listening...";
}
}
void Server::incomingConnection(int socketDescriptor){
qDebug() << socketDescriptor << "Connecting...";
ServerThread *thread = new ServerThread(socketDescriptor, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
sever.h
#ifndef SERVER_H
#define SERVER_H
#include <QTcpServer>
#include <QDebug>
#include "serverthread.h"
class Server : public QTcpServer
{
Q_OBJECT
public:
explicit Server(QObject *parent = 0);
void StartServer();
signals:
public slots:
protected:
void incomingConnection(int socketDescriptor);
};
#endif // SERVER_H
serverthread.cpp
#include "serverthread.h"
ServerThread::ServerThread(int id, QObject *parent) :
QThread (parent)
{
this->socketDescriptor = id;
}
void ServerThread::run(){
//thread starts here
qDebug() << socketDescriptor << " Starting thread";
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor)){
emit error(socket->error());
return;
}
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::DirectConnection);
qDebug() << socketDescriptor << " Client connected";
//make this thread a loop
exec();
}
void ServerThread::readyRead(){
Data = socket->readAll();
qDebug() << socketDescriptor << " Data in: " << Data;
socket->write(Data);
}
void ServerThread::disconnected(){
qDebug() << socketDescriptor << " Disconnected";
socket->deleteLater();
exit(0);
}
serverthread.h
#ifndef SERVERTHREAD_H
#define SERVERTHREAD_H
#include <QThread>
#include <QTcpSocket>
#include <QDebug>
class ServerThread : public QThread
{
Q_OBJECT
public:
QByteArray Data;
explicit ServerThread(int id, QObject *parent = 0);
void run();
signals:
void error(QTcpSocket::SocketError socketerror);
public slots:
void readyRead();
void disconnected();
public slots:
private:
QTcpSocket *socket;
int socketDescriptor;
};
#endif // SERVERTHREAD_H
The goal is to display all the application output shown in QtCreator to a QTextEdit as a debug console window so with the same application only those who have password are allowed to see the console window while normal users cannot. There is an exe with several dlls. All std::cout from DLLs and qDebug are needed to be shown in the debug console window.
To achieve this, I have followed
http://www.qtforum.org/article/39768/redirecting-std-cout-std-cerf-qdebug-to-qtextedit.html
The code works great for single thread but is hanged when a thread is started to call functions in DLL. I would like to know how to fix the problem.
code
In mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QObject>
#include <QThread>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_qd = new Q_DebugStream(std::cout,ui->textEdit); //Redirect Console output to QTextEdit
m_qd->Q_DebugStream::registerQDebugMessageHandler(); //Redirect qDebug() output to QTextEdit
connect(ui->pushButtonSingleThreadTest, SIGNAL(clicked()),this,SLOT(SingleThreadTest()));
connect(ui->pushButtonMultiThreadTest, SIGNAL(clicked()),this,SLOT(MultiThreadTest()));
}
void MainWindow::SingleThreadTest()
{
run();
}
void MainWindow::MultiThreadTest()
{
QThread *workerThread= new QThread;
ThreadWorker *worker = new ThreadWorker();
worker->moveToThread(workerThread);
connect(workerThread, SIGNAL(started()), worker, SLOT(doWork()));
connect(worker, SIGNAL(finished()), workerThread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
workerThread->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
In mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "q_debugstream.h"
#include "../ToyProj1/Header.h"
namespace Ui {
class MainWindow;
}
class ThreadWorker : public QObject
{
Q_OBJECT
public:
ThreadWorker()
{
}
private:
signals:
void finished();
public slots:
void doWork()
{
run();
emit finished();
}
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void SingleThreadTest();
void MultiThreadTest();
private:
Ui::MainWindow *ui;
Q_DebugStream* m_qd;
};
#endif // MAINWINDOW_H
in q_debugstream.h
#ifndef Q_DEBUGSTREAM_H
#define Q_DEBUGSTREAM_H
#include <iostream>
#include <streambuf>
#include <string>
#include "QTextEdit.h"
class Q_DebugStream : public std::basic_streambuf<char>
{
public:
Q_DebugStream(std::ostream &stream, QTextEdit* text_edit) : m_stream(stream)
{
log_window = text_edit;
m_old_buf = stream.rdbuf();
stream.rdbuf(this);
}
~Q_DebugStream()
{
m_stream.rdbuf(m_old_buf);
}
static void registerQDebugMessageHandler(){
qInstallMessageHandler(myQDebugMessageHandler);
}
private:
static void myQDebugMessageHandler(QtMsgType, const QMessageLogContext &, const QString &msg)
{
std::cout << msg.toStdString().c_str();
}
protected:
//This is called when a std::endl has been inserted into the stream
virtual int_type overflow(int_type v)
{
if (v == '\n')
{
log_window->append("");
}
return v;
}
virtual std::streamsize xsputn(const char *p, std::streamsize n)
{
QString str(p);
if(str.contains("\n")){
QStringList strSplitted = str.split("\n");
log_window->moveCursor (QTextCursor::End);
log_window->insertPlainText (strSplitted.at(0)); //Index 0 is still on the same old line
for(int i = 1; i < strSplitted.size(); i++){
log_window->append(strSplitted.at(i));
}
}else{
log_window->moveCursor (QTextCursor::End);
log_window->insertPlainText (str);
}
return n;
}
private:
std::ostream &m_stream;
std::streambuf *m_old_buf;
QTextEdit* log_window;
};
#endif // Q_DEBUGSTREAM_H
In DLL,
int run()
{
std::cout << "Hello World" << std::endl;
return 0;
}
The code sample is uploaded to github for reference. Build ToyProj1 and ToyProj1GUI when repeat the problem.
https://github.com/kuwt/ToyProject.git
With the help comments in question, this solution works well with signal and slot mechanism. std::cout and qDebug are redirected to QTextEdit.
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
// Setup QMessageCatch
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
qInstallMessageHandler(MainWindow::QMessageOutput);
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include <QTextEdit>
#include "q_debugstream.h"
namespace Ui {
class MainWindow;
}
class ThreadWorker : public QObject
{
Q_OBJECT
public:
ThreadWorker()
{
}
private:
signals:
void finished();
public slots:
void doWork()
{
std::cout<< "Hello World2" <<std::endl;
qDebug() << "Hello World2q" ;
emit finished();
}
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
// QMessage
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
static void QMessageOutput(QtMsgType , const QMessageLogContext &, const QString &msg);
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
public slots:
void SingleThreadTest();
void MultiThreadTest();
private:
Ui::MainWindow *ui;
// MessageHandler for display and ThreadLogStream for redirecting cout
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
MessageHandler *msgHandler = Q_NULLPTR;
ThreadLogStream* m_qd;
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QObject>
#include <QThread>
// Catch QMessage, redirect to cout
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
void MainWindow::QMessageOutput(QtMsgType , const QMessageLogContext &, const QString &msg)
{
std::cout<<msg.toStdString().c_str()<<std::endl;
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Set up ThreadLogStream, which redirect cout to signal sendLogString
// Set up MessageHandler, wgucg catch message from sendLogString and Display
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
m_qd = new ThreadLogStream(std::cout); //Redirect Console output to QTextEdit
this->msgHandler = new MessageHandler(this->ui->textEdit, this);
connect(m_qd, &ThreadLogStream::sendLogString, msgHandler, &MessageHandler::catchMessage);
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
connect(ui->pushButtonSingleThreadTest, SIGNAL(clicked()),this,SLOT(SingleThreadTest()));
connect(ui->pushButtonMultiThreadTest, SIGNAL(clicked()),this,SLOT(MultiThreadTest()));
}
void MainWindow::SingleThreadTest()
{
std::cout<< "Hello World1" <<std::endl;
qDebug() << "Hello World1q" ;
}
void MainWindow::MultiThreadTest()
{
QThread *workerThread= new QThread;
ThreadWorker *worker = new ThreadWorker();
worker->moveToThread(workerThread);
connect(workerThread, SIGNAL(started()), worker, SLOT(doWork()));
connect(worker, SIGNAL(finished()), workerThread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
workerThread->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
q_debugstream.h
#ifndef ThreadLogStream_H
#define ThreadLogStream_H
#include <iostream>
#include <streambuf>
#include <string>
#include <QScrollBar>
#include "QTextEdit"
#include "QDateTime"
// MessageHandler
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
class MessageHandler : public QObject
{
Q_OBJECT
public :
MessageHandler(QTextEdit *textEdit, QObject * parent = Q_NULLPTR) : QObject(parent), m_textEdit(textEdit){}
public slots:
void catchMessage(QString msg)
{
this->m_textEdit->append(msg);
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
private:
QTextEdit * m_textEdit;
};
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
class ThreadLogStream : public QObject, public std::basic_streambuf<char>
{
Q_OBJECT
public:
ThreadLogStream(std::ostream &stream, QObject * parent = Q_NULLPTR) :QObject(parent), m_stream(stream)
{
m_old_buf = stream.rdbuf();
stream.rdbuf(this);
}
~ThreadLogStream()
{
// output anything that is left
if (!m_string.empty())
{
emit sendLogString(QString::fromStdString(m_string));
}
m_stream.rdbuf(m_old_buf);
}
protected:
virtual int_type overflow(int_type v)
{
if (v == '\n')
{
emit sendLogString(QString::fromStdString(m_string));
m_string.erase(m_string.begin(), m_string.end());
}
else
m_string += v;
return v;
}
virtual std::streamsize xsputn(const char *p, std::streamsize n)
{
m_string.append(p, p + n);
long pos = 0;
while (pos != static_cast<long>(std::string::npos))
{
pos = static_cast<long>(m_string.find('\n'));
if (pos != static_cast<long>(std::string::npos))
{
std::string tmp(m_string.begin(), m_string.begin() + pos);
emit sendLogString(QString::fromStdString(tmp));
m_string.erase(m_string.begin(), m_string.begin() + pos + 1);
}
}
return n;
}
private:
std::ostream &m_stream;
std::streambuf *m_old_buf;
std::string m_string;
signals:
void sendLogString(const QString& str);
};
#endif // ThreadLogStream_H
for long transactions, you can add:
QCoreApplication::processEvents();
in the catchMessage(QString(msg) method of the class MessageHandler in q_debugstream.h, after the append() call.
This updates textEdit 'as soon as possible'.
I'm trying to send an audio stream from a microphone via TCP in a thread other than the main thread. Therefore I've set up a server an I'm listening for incoming connections. Once a client connects, I want to send it the audio stream. I've read the Qt Documentation about QTcpServer, Multithreading, and QtMultimedia. I've also looked at this website for example code about multithreading and TCP servers in Qt. The problem is this message that I get during runtime:
QObject: Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine(0xae802a78), parent's thread is MyThread1(0x1856d28), current thread is QThread(0x1838aa0)
this is my code:
in file myserver.h
#ifndef MYSERVER_H
#define MYSERVER_H
#include <QtNetwork>
#include <QTcpServer>
#include <mythread.h>
#include <QtMultimediaKit/QAudioFormat>
#include <QtMultimediaKit/QAudioInput>
#include <QtMultimediaKit/QAudioDeviceInfo>
class MyServer : public QTcpServer
{
Q_OBJECT
public:
explicit MyServer(QObject *parent = 0);
void startServer();
signals:
public slots:
protected:
void incomingConnection(int socketDescriptor);
private:
QAudioInput *audioInput;
};
#endif // MYSERVER_H
in file myserver.cpp
#include "myserver.h"
MyServer::MyServer(QObject *parent) :
QTcpServer(parent)
{
}
void MyServer::startServer()
{
int port = 12345;
QString ipAddress;
QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
for (int i = 0; i < ipAddressesList.size(); ++i)
{
if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address())
{
ipAddress = ipAddressesList.at(i).toString();
break;
}
}
if(!this->listen( QHostAddress(ipAddress),port ) )
{
qDebug() << "Could not start server";
}
else
{
qDebug() << "The server is running on\n\nIP: "<< ipAddress;
qDebug() << "\nport: " << this->serverPort() << "\n\n";
}
}
void MyServer::incomingConnection(int socketDescriptor)
{
qDebug() << socketDescriptor << " Connecting...";
QAudioFormat format;
format.setSampleRate(44100);
format.setChannelCount(1);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);
QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
if (!info.isFormatSupported(format))
{
qWarning()<<"default format not supported try to use nearest";
format = info.nearestFormat(format);
}
audioInput = new QAudioInput(format, this);
MyThread1 *thread = new MyThread1(socketDescriptor,audioInput, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
in file mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QTcpSocket>
#include <QDebug>
#include <QtMultimediaKit/QAudioInput>
class MyThread1 : public QThread
{
Q_OBJECT
public:
explicit MyThread1( int ID, QAudioInput *spk, QObject *parent = 0);
void run();
signals:
void error(QTcpSocket::SocketError socketerror);
public slots:
void sendData();
void disconnected();
private:
QTcpSocket *socket;
int socketDescriptor;
QAudioInput *speaker;
};
#endif // MYTHREAD_H
in file mythread.cpp
#include "mythread.h"
MyThread1::MyThread1( int ID, QAudioInput *spk, QObject *parent) :
QThread(parent)
{
this->socketDescriptor = ID;
this->speaker = spk;
}
void MyThread1::run()
{
qDebug() << " Thread started";
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor))
{
emit error(socket->error());
return;
}
connect( speaker->start(), SIGNAL( readyRead() ), this, SLOT( sendData() ) , Qt::DirectConnection);
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
qDebug() << socketDescriptor << " Microphone connected";
exec();
}
void MyThread1::sendData()
{
QByteArray Data = speaker->start()->readAll();
QDataStream l_vStream(&Data, QIODevice::WriteOnly);
l_vStream.setByteOrder(QDataStream::LittleEndian);
socket->write(Data, Data.length());
socket->waitForBytesWritten();
}
void MyThread1::disconnected( )
{
qDebug() << socketDescriptor << "Mic Disconnected";
speaker->stop();
delete speaker;
socket->deleteLater();
exit(0);
}
in file main.cpp
#include <QCoreApplication>
#include <myserver.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyServer server;
server.startServer();
return a.exec();
}
Any help would really be appreciated. Thanks.
I have been trying to get this simple example using threads activated by pushbuttons to work. It is based off of the solution in the question below:
How to implement frequent start/stop of a thread (QThread)
The main differences between the example solution above and my code below are:
I used a QWidget instead of MainWindow
I changed the name of signals for clarity
My code contains debugging information
I experimented with eliminating the signals created by worker as the didn't appear to do anything
It appears that the start/stop signals are not triggering their corresponding slots, but I am not experienced enough to troubleshoot why.
Additionally, I am unsure of the purpose of the signal:
SignalToObj_mainThreadGUI()
Is that just something that could be used and is not?
I have been trying to get this code to work for some time, so any help would be greatly appreciated.
main.cpp
#include "threadtest.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ThreadTest w;
w.show();
return a.exec();
}
threadtest.h
#include <QWidget>
#include <QThread>
#include "worker.h"
namespace Ui
{
class ThreadTest;
}
class ThreadTest : public QWidget
{
Q_OBJECT
public:
explicit ThreadTest(QWidget *parent = 0);
~ThreadTest();
signals:
void startWorkSignal();
void stopWorkSignal();
private slots:
void on_startButton_clicked();
void on_stopButton_clicked();
private:
Ui::ThreadTest *ui;
worker *myWorker;
QThread *WorkerThread;
};
threadtest.cpp
#include "threadtest.h"
#include "ui_threadtest.h"
ThreadTest::ThreadTest(QWidget *parent) :
QWidget(parent),
ui(new Ui::ThreadTest)
{
ui->setupUi(this);
myWorker = new worker;
WorkerThread = new QThread;
myWorker->moveToThread(WorkerThread);
connect(this,
SIGNAL(startWorkSignal()),
myWorker,
SLOT(StartWork())
);
connect(this,
SIGNAL(stopWorkSignal()),
myWorker,
SLOT(StopWork())
);
//Debug
this->dumpObjectInfo();
myWorker->dumpObjectInfo();
}
ThreadTest::~ThreadTest()
{
delete ui;
}
void ThreadTest::on_startButton_clicked()
{
qDebug() << "startwork signal emmitted";
emit startWorkSignal();
}
void ThreadTest::on_stopButton_clicked()
{
qDebug() << "stopwork signal emmitted";
emit stopWorkSignal();
}
worker.h
#include <QObject>
#include <QDebug>
class worker : public QObject {
Q_OBJECT
public:
explicit worker(QObject *parent = 0);
~worker();
signals:
void SignalToObj_mainThreadGUI();
//void running();
//void stopped();
public slots:
void StopWork();
void StartWork();
private slots:
void do_Work();
private:
volatile bool running, stopped;
};
worker.cpp
#include "worker.h"
worker::worker(QObject *parent) : QObject(parent), stopped(false),
running(false)
{
qDebug() << "running: " << running;
qDebug() << "stopped: " << stopped;
}
worker::~worker() {}
void worker::do_Work()
{
qDebug() << "inside do Work";
emit SignalToObj_mainThreadGUI();
if (!running || stopped) return;
// actual work here
/*
for (int i = 0; i < 100; i++)
{
qDebug() << "count: " + i;
}
*/
QMetaObject::invokeMethod(this, "do_Work", Qt::QueuedConnection);
}
void worker::StopWork()
{
qDebug() << "inside StopWork";
stopped = true;
running = false;
//emit stopped();
}
void worker::StartWork()
{
qDebug() << "inside StartWork";
stopped = false;
running = true;
//emit running();
do_Work();
}
You should write
WorkerThread->start();
Or you can use the thread of the ThreadTest object instead the WorkerThread (in this case the WorkerThread is needless):
myWorker->moveToThread(thread()); // this->thread
The slots are not triggered, because you have moved myWork to the thread WorkerThread, but didnot run an event loop in that thread. In threadtest.cpp, add
WorkerThread .start();
after
myWorker = new worker;
WorkerThread = new QThread;
myWorker->moveToThread(WorkerThread);