Hello. I have a serious problem that I can not solve.
I have a device that sends a request to the board and is waiting for a response. Work with the device is done in a separate thread, so as not to slow down the gui. Also there is a class of algorithms that works in another thread. The algorithm calls the methods to open / close.

MainWindow:
Qt Code:
  1. /***mainwindow.h***/
  2. #ifndef MAINWINDOW_H
  3. #define MAINWINDOW_H
  4.  
  5. #include <QMainWindow>
  6. #include <QThread>
  7. #include "deviceworker.h"
  8. #include "algorithm.h"
  9.  
  10. namespace Ui {
  11. class MainWindow;
  12. }
  13.  
  14. class MainWindow : public QMainWindow
  15. {
  16. Q_OBJECT
  17.  
  18. public:
  19. explicit MainWindow(QWidget *parent = 0);
  20. ~MainWindow();
  21. FirstDevice *device;
  22. Algorithm *algorithm;
  23. QThread *deviceThread;
  24. QThread *algorithmThread;
  25.  
  26. private slots:
  27. void on_pushButton_clicked();
  28.  
  29. private:
  30. Ui::MainWindow *ui;
  31.  
  32. };
  33.  
  34. #endif // MAINWINDOW_H
  35.  
  36. /***mainwindow.cpp***/
  37. #include "ui_mainwindow.h"
  38.  
  39. MainWindow::MainWindow(QWidget *parent) :
  40. QMainWindow(parent),
  41. ui(new Ui::MainWindow)
  42. {
  43. ui->setupUi(this);
  44. }
  45.  
  46. MainWindow::~MainWindow()
  47. {
  48. delete ui;
  49.  
  50. QThread *deviceThread = new QThread();
  51. QThread *algorithmThread = new QThread();
  52. device = new FirstDevice();
  53. device->setReadTimer(333);
  54. device->moveToThread(deviceThread);
  55.  
  56. algorithm = new Algorithm(device);
  57. algorithm->moveToThread(algorithmThread);
  58. deviceThread->start(QThread::TimeCriticalPriority);
  59. algorithmThread->start();
  60. }
  61.  
  62. void MainWindow::on_pushButton_clicked()
  63. {
  64. algorithm->run();
  65. }
To copy to clipboard, switch view to plain text mode 

DeviceWorker:
Qt Code:
  1. /***deviceworker.h***/
  2. #ifndef DEVICEWORKER_H
  3. #define DEVICEWORKER_H
  4.  
  5. #include <QTimer>
  6. #include <QtSerialPort/QSerialPort>
  7. #include <QMutex>
  8. #include <QDebug>
  9. #include <QObject>
  10.  
  11. using namespace std;
  12.  
  13.  
  14. class FirstDevice : public QObject {
  15. Q_OBJECT
  16.  
  17. private:
  18. QTimer readTimer;
  19. public:
  20. explicit FirstDevice(QObject *parent = 0);
  21. ~FirstDevice(){}
  22.  
  23. void setReadTimer(int ms){
  24. readTimer.start(ms);
  25. }
  26.  
  27. public slots:
  28. bool open(int id){
  29. emit switchStateSig(id, true);
  30. }
  31. bool close(int id){
  32. emit switchStateSig(id, false);
  33. }
  34. bool getAllStates();
  35.  
  36. private slots:
  37. bool switchState(int id, bool state);
  38.  
  39. signals:
  40. void remoteSignal(bool);
  41. void status(int, bool, bool);
  42. void switchStateSig(int, bool);
  43. };
  44.  
  45.  
  46. class ComPort : public QObject { //singltone
  47. Q_OBJECT
  48. private:
  49. QSerialPort *serial;
  50. QMutex *mutex;
  51. explicit ComPort(QObject *parent = 0){
  52. mutex = new QMutex();
  53. serial = new QSerialPort();
  54. connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(handleError(QSerialPort::SerialPortError)));
  55. }
  56.  
  57. ~ComPort(){}
  58. ComPort(ComPort const&) = delete;
  59. ComPort& operator= (ComPort const&) = delete;
  60. public:
  61. static ComPort& get()
  62. {
  63. static ComPort instance;
  64. return instance;
  65. }
  66.  
  67. void open(){
  68. if(serial->isOpen())
  69. close();
  70. serial->setPortName("COM2");
  71. if (serial->open(QIODevice::ReadWrite)) {
  72. if (serial->setBaudRate(QSerialPort::Baud115200)
  73. && serial->setFlowControl(QSerialPort::NoFlowControl)) {
  74. qDebug() << "open";
  75. } else {
  76. qDebug() << QString(serial->errorString());
  77. serial->close();
  78. }
  79. }
  80. }
  81. void close(){serial->close();}
  82. QByteArray requestResponse(const QByteArray &data){
  83. mutex->lock();
  84. qDebug() << "-------------------------";
  85. if(!serial->isOpen())
  86. open();
  87. int attempts = 1;
  88. QByteArray readBuf;
  89. while (attempts <= 3) {
  90. if (serial->isWritable())
  91. {
  92. serial->write(data);
  93. serial->waitForBytesWritten(3);
  94. while (serial->waitForReadyRead(300)) { //(wait 300ms). Here, randomly breaks down
  95. readBuf += serial->readAll();
  96. if (readBuf.size() == 4){
  97. close();
  98. mutex->unlock();
  99. return readBuf;
  100. }
  101. }
  102. readBuf.clear();
  103. close();
  104. open();
  105. attempts++;
  106. }
  107. else
  108. {
  109. qDebug() << "port is not written";
  110. close();
  111. mutex->unlock();
  112. return 0;
  113. }
  114. }
  115. close();
  116. mutex->unlock();
  117. return 0;
  118. }
  119.  
  120. private slots:
  121. void handleError(QSerialPort::SerialPortError error){
  122. if (error == QSerialPort::ResourceError) {
  123. close();
  124. qDebug() << "Error! ";
  125. }
  126. }
  127. };
  128.  
  129. #endif // DEVICEWORKER_H
  130.  
  131.  
  132. /***deviceworker.cpp***/
  133. #include "deviceworker.h"
  134.  
  135.  
  136. FirstDevice::FirstDevice(QObject *parent):QObject(parent)
  137. {
  138. connect(this, SIGNAL(switchStateSig(int, bool)), this, SLOT(switchState(int, bool)));
  139. connect(&readTimer, SIGNAL(timeout()), this, SLOT(getAllStates()));
  140. }
  141.  
  142. bool FirstDevice::getAllStates()
  143. {
  144. arr.resize(2);
  145. arr[0] = 0xAB;
  146. arr[1] = 0x01;
  147. QByteArray response = ComPort::get().requestResponse(arr);
  148. if(response[0] == arr[0])
  149. {
  150. emit remoteSignal(1);
  151. return 1;
  152. }
  153. emit remoteSignal(0);
  154. return 0;
  155. }
  156.  
  157. bool FirstDevice::switchState(int id, bool state)
  158. {
  159. arr.resize(2);
  160. arr[0] = 0xAB;
  161. arr[1] = 0x01;
  162.  
  163. QByteArray response = ComPort::get().requestResponse(arr);
  164. if(response[0] == arr[0]) //ok
  165. {
  166. emit status(id, state, true);
  167. return 1;
  168. }
  169. emit status(id, state, false);
  170. return 0;
  171. }
To copy to clipboard, switch view to plain text mode 

algorithm:
Qt Code:
  1. #ifndef ALGORITHM_H
  2. #define ALGORITHM_H
  3. #include <QObject>
  4. #include "deviceworker.h"
  5. class Algorithm: public QObject
  6. {
  7. Q_OBJECT
  8. private:
  9. FirstDevice *device;
  10. public:
  11. Algorithm(FirstDevice *device_){
  12. device = device_;
  13. }
  14. void run(){
  15. device->open(3); //Here I must wait for an answer
  16. //do something
  17. device->close(3); //Here I must wait for an answer
  18. }
  19. };
  20.  
  21. #endif // ALGORITHM_H
To copy to clipboard, switch view to plain text mode 

So, I have two problems:
1. How to wait for a response from a card without using the method waitForReadyRead()? This is what I need, but I can not use it. The program periodically falls arbitrarily in this place. I read that this function is unstable on windows.
2. Inside the Algorithm method run(), I open / close the device. But since the device and the algorithm work in different threads, I had to connect them with signals and slots. Therefore, I do not wait for an answer from the board, but I go further. That is, in fact, the board may not respond, and I will ignore it, which is very bad.

I apologize for the long post, but I do not know how to make it even shorter.