[SOLVED]When using QSerialPort to receive data bytes in a non-GUI thread, should I create QSerialPort object in that thread?[solved]
-
Hi, Everyone!
I want to use QSerialPort to communicate with another device through serial port. I declared QserialPort object as a member variable of a dialog. From this dialog I can get datas and send them with widget's click signal. I also started a thread to receive datas sent by remote device with same QserialPort object in dialog. But I found the data-receiving operation in thread did not work properly at all time: for example, when remote device send ASCII charactor sequence, they can be received properly in thread, but when non-ASCII charactor sequence is sent (just like "\x00\x49\xF2\x87....."), I can't receive them in thread.
My codesnippet is:while(isRunning()) { if (m_port.waitForReadyRead()) { QByteArray dataread = m_port.readAll(); // process datas } }
while debuging in non-ASCII sequence, I found the function m_port.waitForReadyRead() does not return. But in ASCII sequence it returned properly.
In some posts of this forum, it is said that the QSerialPort object should be constructed in thread. Is it the reason about unproperly data-receiving in non-ASCII sequence?
Thanks!
-
Hi,
Indeed you have thread affinity problems here. By the way, why not use your serial port in asynchronous mode ?
-
Hi,
Indeed you have thread affinity problems here. By the way, why not use your serial port in asynchronous mode ?
@SGaist
Hi, Mr. SGaist. I've tried in asynchronous mode just earlier, and found there was the same untriggerable problem in receiving datas, so I had to turn to synchronous mode.
After reading your suggestion, I tried asynchronous mode again by starting a new project. I found it seemed to be worked. So I guess there must be something wrong in my original project. But, unfortunately, the original code has been changed and I can't find what's wrong with it.
Now I'm trying to implement my work in a new started project, and I hope it will get better.Another point about using synchronous mode, Soon after this program,I will write a program which will receiving datas in much more higher transmision rate than normally. The data transmision rate may be 1.x Mbps(using MOXA serial board). I worry about data losing in asynchrous mode, for the data receiving is done in event loop of GUI main thread. So I think I still had to use the synchronous mode in that proram, and I still had to solve the conflict between background data receiving and foreground data sending triggered by UI actions. Would you like to give me some suggestion about that?
Thank you very much!
-
Nothing forbids you to handle your serial port in a secondary thread, parse the data there and the send what you need to the GUI thread through signals and slots
-
Nothing forbids you to handle your serial port in a secondary thread, parse the data there and the send what you need to the GUI thread through signals and slots
@SGaist
Hi, Mr.SGaist,
Thank you for your answers. I had solved my problem, and found that the error is caused by the leak in my code :
In my sub thread, I stored the received datas into a QByteArray object which is declared as a local object, and emited a signal with parameter set to that QByteArray object. I found that after the signal was emited, the sub thread did not wait for the execution of the corresponding slot functions. So while the slot functions was executed in main thread's event loop, the QByteArray object passed to it had already been destroyed, and the slot function got an invalid object, and then the memory access leak happened, and strenge things (such as data couldn't be received) began to occure.based on my experience, I think some warning comments should be added into Qt's API documents, to avoid the unecessaried mistakes on Qt newbies, just like me. Do you think so?
-
Are you by any chance allocating your QByteArray on the heap or sending a pointer to it ? If so, then you have a design error
-
Are you by any chance allocating your QByteArray on the heap or sending a pointer to it ? If so, then you have a design error
@SGaist
Yes, it is I make mistakes in my design. I just sovled it by making QByteArray object which will be passed to slot function as a member object of the sub thread class. I do not prefer too much dynamic allocating of memory for the considering of stability and performance consideration, even Qt has provided many methods and frameworks to avoid memory leaking and performance lossing. Well, that's only my personal preference ^_^ -
@SGaist
Hi, Mr.SGaist,
Thank you for your answers. I had solved my problem, and found that the error is caused by the leak in my code :
In my sub thread, I stored the received datas into a QByteArray object which is declared as a local object, and emited a signal with parameter set to that QByteArray object. I found that after the signal was emited, the sub thread did not wait for the execution of the corresponding slot functions. So while the slot functions was executed in main thread's event loop, the QByteArray object passed to it had already been destroyed, and the slot function got an invalid object, and then the memory access leak happened, and strenge things (such as data couldn't be received) began to occure.based on my experience, I think some warning comments should be added into Qt's API documents, to avoid the unecessaried mistakes on Qt newbies, just like me. Do you think so?
@JohnYork said:
based on my experience, I think some warning comments should be added into Qt's API documents, to avoid the unecessaried mistakes on Qt newbies, just like me. Do you think so?
It is tempting to want to place the blame on your framework or compiler however in my experience 99.9999% of the time it is the design or the programmer that is causing the issue.
For the most part the code was exactly what you programmed it to do. What makes things harder now days is you really don't know how long an object lives when it is created in some strange place. Most objects in the framework have a parent pointer and when the parent dies or if you don't use parent (in some cases) and the object dies because of scope then all bets are off if you have pointers to that object.
In the "old" days we pretty much managed everything ourselves. You created something, you had to get rid of it.
Even with the newer ways of managing items I still find that at times knowing exactly when an object is valid and when it is not is invaluable. Therefore somethings need to be singletons that you create and leave around until you decide you are done with them.
Anyway I doubt there is any comment that could be added to docs to help out with these concepts. The Qt docs document the use of the framework, not how to manage objects and object scope.
Since those principles apply to ALL C++ objects a standard C++ tutorial, book or online course will give you what you need. This forum with the great people here can help to fill in the gaps on Qt related stuff. You'll find the people here amazingly knowledgeable and talented.