How to increase QT Gui thread priority in linux [duplicate] - linux

This question already has an answer here:
Set priority to GUI thread in Qt
(1 answer)
Closed 6 years ago.
Is there a way to set gui thread priority higher than others threads of my app in Linux?
I also know that setPriority function in QThread class, not working in linux.
however, is there a solution to do it?
(i am working with qt4.8)
thanks a lot

You shouldn't need to do that. Your GUI should only be displaying the most recent image. Most likely your design forces the GUI to display the outdated images even if they are not relevant anymore.
The typical way this would be achieved in Qt is by having an image viewer class that only displays the most recently set image:
class ImageViewer : public QWidget {
Q_OBJECT
QImage m_img;
bool m_new;
void paintEvent(QPaintEvent *) {
QPainter p(this);
p.drawImage(0, 0, m_img);
m_new = false;
}
public:
ImageViewer(QWidget * parent = 0) : QWidget(parent), m_new(false) {
setAttribute(Qt::WA_OpaquePaintEvent);
}
Q_SLOT void setImage(const QImage & img) {
if (m_new) qDebug() << "Viewer dropped frame!";
m_img = img;
m_new = true;
if (m_img.size() != size()) setFixedSize(m_img.size());
update();
}
};
You can then send signals connected to the setImage slot. Those signals can come from a QObject that has been moved to another thread.
See here for a complete example.

In GUI thread (for example in main()) execute:
QThread::currentThread()->setPriority(QThread::HighPriority);
See Qt docs for more possible priority values.

Related

QSerialPort with no GUI, no thread: QObject::startTimer: Timers can only be used with threads started with QThread

I'm doing a DLL with no GUI (TEMPLATE = lib), using QSerialPort. I don't create threads and I don't need any: I have no GUI and having a blocking serial port operation is no problem, it is what I want.
When doing:
while (!serial_uart->isWritable());
while (!serial_uart->write(frame));
I get:
QObject::startTimer: Timers can only be used with threads started with QThread
Question: how to use QSerialPort in a library without GUI without triggering this error?
Note: I first thought the problem was coming from serial_uart->waitForReadyRead(timeout) but even without this and only serial_uart->write() I already have this problem.
Minimal reproducible DLL example:
test.cpp
#include "test.h"
extern "C" {
__declspec(dllexport) Test* new_Test() { return new Test(); }
__declspec(dllexport) void DoTest(Test *t) { t->DoTest(); }
}
Test::Test() :QObject()
{
qDebug("Hello");
}
void Test::DoTest()
{
this->serialport = new QSerialPort();
this->serialport ->setPortName("COM12");
this->serialport->setBaudRate(QSerialPort::Baud19200);
this->serialport->open(QIODevice::ReadWrite);
while (!this->serialport->isWritable());
while (!this->serialport->write("hello"));
}
test.h
#include <QSerialPort>
class Test : public QObject
{
Q_OBJECT
public:
Test();
void DoTest();
QSerialPort *serialport;
};
test.pro
TEMPLATE = lib
TARGET = test
QT += serialport
INCLUDEPATH += .
HEADERS += test.h
SOURCES += test.cpp
When I call the release/test.dll from Python I have this:
from ctypes import *
dll = CDLL(r"release\test.dll")
dll.new_Test.restype = c_void_p
dll.new_Test.argtypes = []
dll.DoTest.restype = None
dll.DoTest.argtypes = [c_void_p]
t = dll.new_Test()
dll.DoTest(t)
Hello
QObject::startTimer: Timers can only be used with threads started with QThread
Most of the QIODevice based classes (like Qt sockets or serial port) want to live in a Qt based thread and also their functions needs to be called from the same thread where the object was created.
For that reason I've usually solved this by:
Create wrapper class (QObject based with Q_OBJECT macro for signal/slot functionality) for the QIODevice based class you are about to use. For each function you are planning on using create a slot function on your wrapper class which then calls the equivalent funtion in the QIODevice:
qint64 MySerialPort::write(const QByteArray &data)
{
// m_serialPort is created with new QSerialPort in constructor of MySerialPort.
return m_serialPort->write(data);
}
Create a QThread class that in its run function creates an instance of MySerialPort (with new MySerialPort) and just calls exec() after that. Now MySerialPort lives in an event loop and is able to send and receive signals/slots.
void MySerialPortThread::run()
{
m_serialPort = new MySerialPort();
exec();
delete m_serialPort; // Automatic deletion after thread is stopped.
}
The thread could also return a pointer to the instance for easier access from outside to connect signals and slots.
MySerialPort* MySerialPortThread::serialPort()
{
return m_serialPort; // Instance of MySerialPort class
}
In your main code create signals that match the slots of the MySerialPort and connect them.
signals:
qint64 writeSerial(const QByteArray& data);
void MyMainClass::connectSignalsAndSlots()
{
MySerialPort* serialPort = m_serialThread->serialPort();
connect(this, &MyMainClass::writeSerial, serialPort, &MySerialPort::write, Qt::BlockingQueuedConnection); // Use either QueuedConnection or BlockingQueuedConnection to force the execution of the slot to the MySerialThread.
}
Emit the signals to access the QSerialPort.
emit writeSerial(dataByteArray);

How to send signal/data from a worker thread to main thread?

I'll preface this by saying that I'm delving into multithreading for the first time. Despite a lot of reading on concurrency and synchronization, I'm not readily seeing a solution for the requirements I've been given.
Using C++11 and Boost, I'm trying to figure out how to send data from a worker thread to a main thread. The worker thread is spawned at the start of the application and continuously monitors a lock free queue. Objects populate this queue at various intervals. This part is working.
Once the data is available, it needs to be processed by the main thread since another signal will be sent to the rest of the application which cannot be on a worker thread. This is what I'm having trouble with.
If I have to block the main thread through a mutex or a condition variable until the worker thread is done, how will that improve responsiveness? I might as well just stay with a single thread so I have access to the data. I must be missing something here.
I have posted a couple questions, thinking that Boost::Asio was the way to go. There is an example of how signals and data can be sent between threads, but as the responses indicate, things get quickly overly-complicated and it's not working perfectly:
How to connect signal to boost::asio::io_service when posting work on different thread?
Boost::Asio with Main/Workers threads - Can I start event loop before posting work?
After speaking with some colleagues, it was suggested that two queues be used -- one input, one output. This would be in shared space and the output queue would be populated by the worker thread. The worker thread is always going but there would need to be a Timer, probably at the application level, that would force the main thread to examine the output queue to see if there were any pending tasks.
Any ideas on where I should direct my attention? Are there any techniques or strategies that might work for what I'm trying to do? I'll be looking at Timers next.
Thanks.
Edit: This is production code for a plugin system that post-processes simulation results. We are using C++11 first wherever possible, followed by Boost. We are using Boost's lockfree::queue. The application is doing what we want on a single thread but now we are trying to optimize where we see that there are performance issues (in this case, a calculation happening through another library). The main thread has a lot of responsibilities, including database access, which is why I want to limit what the worker thread actually does.
Update: I have already been successful in using std::thread to launch a worker thread that examines a Boost lock::free queue and processes tasks placed it in. It's step 5 in #Pressacco's response that I'm having trouble with. Any examples returning a value to the main thread when a worker thread is finished and informing the main thread, rather than simply waiting for the worker to finish?
If your objective is develop the solution from scratch (using native threads, queues, etc.):
create a thread save queue queue (Mutex/CriticalSection around add/remove)
create a counting semaphore that is associated with the queue
have one or more worker threads wait on the counting semaphore (i.e. the thread will block)
the semaphore is more efficient than having the thread constantly poll the queue
as messages/jobs are added to the queue, increment the semaphore
a thread will wake up
the thread should remove one message
if a result needs to be returned...
setup another: Queue+Semaphore+WorkerThreads
ADDITIONAL NOTES
If you decide to implement a thread safe queue from scratch, take a look at:
Synchronization between threads using Critical Section
With that said, I would take another look at BOOST. I haven't used the library, but from what I hear it will most likely contain some relevant data structures (e.g. a thread safe queue).
My favorite quote from the MSDN:
"When you use multithreading of any sort, you potentially expose
yourself to very serious and complex bugs"
SIDEBAR
Since you are looking at concurrent programming for the first time, you may wish to consider:
Is your objective to build production worthy code , or is this simply a learning exercise?
production? consider us existing proven libraries
learning? consider writing the code from scratch
Consider using a thread pool with an asynchronous callback instead of native threads.
more threads != better
Are threads really needed?
Follow the KISS principle.
The feedback above led me in the right direction for what I needed. The solution was definitely simpler than having to use signals/slots or Boost::Asio as I had previously attempted. I have two lock-free queues, one for input (on a worker thread) and one for output (on the main thread, populated by the worker thread). I use a timer to schedule when the output queue is processed. The code is below; perhaps it is of use to somebody:
//Task.h
#include <iostream>
#include <thread>
class Task
{
public:
Task(bool shutdown = false) : _shutdown(shutdown) {};
virtual ~Task() {};
bool IsShutdownRequest() { return _shutdown; }
virtual int Execute() = 0;
private:
bool _shutdown;
};
class ShutdownTask : public Task
{
public:
ShutdownTask() : Task(true) {}
virtual int Execute() { return -1; }
};
class TimeSeriesTask : public Task
{
public:
TimeSeriesTask(int value) : _value(value) {};
virtual int Execute()
{
std::cout << "Calculating on thread " << std::this_thread::get_id() << std::endl;
return _value * 2;
}
private:
int _value;
};
// Main.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "afxwin.h"
#include <boost/lockfree/spsc_queue.hpp>
#include "Task.h"
static UINT_PTR ProcessDataCheckTimerID = 0;
static const int ProcessDataCheckPeriodInMilliseconds = 100;
class Manager
{
public:
Manager()
{
//Worker Thread with application lifetime that processes a lock free queue
_workerThread = std::thread(&Manager::ProcessInputData, this);
};
virtual ~Manager()
{
_workerThread.join();
};
void QueueData(int x)
{
if (x > 0)
{
_inputQueue.push(std::make_shared<TimeSeriesTask>(x));
}
else
{
_inputQueue.push(std::make_shared<ShutdownTask>());
}
}
void ProcessOutputData()
{
//process output data on the Main Thread
_outputQueue.consume_one([&](int value)
{
if (value < 0)
{
PostQuitMessage(WM_QUIT);
}
else
{
int result = value - 1;
std::cout << "Final result is " << result << " on thread " << std::this_thread::get_id() << std::endl;
}
});
}
private:
void ProcessInputData()
{
bool shutdown = false;
//Worker Thread processes input data indefinitely
do
{
_inputQueue.consume_one([&](std::shared_ptr<Task> task)
{
std::cout << "Getting element from input queue on thread " << std::this_thread::get_id() << std::endl;
if (task->IsShutdownRequest()) { shutdown = true; }
int result = task->Execute();
_outputQueue.push(result);
});
} while (shutdown == false);
}
std::thread _workerThread;
boost::lockfree::spsc_queue<std::shared_ptr<Task>, boost::lockfree::capacity<1024>> _inputQueue;
boost::lockfree::spsc_queue<int, boost::lockfree::capacity<1024>> _outputQueue;
};
std::shared_ptr<Manager> g_pMgr;
//timer to force Main Thread to process Manager's output queue
void CALLBACK TimerCallback(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
if (nIDEvent == ProcessDataCheckTimerID)
{
KillTimer(NULL, ProcessDataCheckPeriodInMilliseconds);
ProcessDataCheckTimerID = 0;
//call function to process data
g_pMgr->ProcessOutputData();
//reset timer
ProcessDataCheckTimerID = SetTimer(NULL, ProcessDataCheckTimerID, ProcessDataCheckPeriodInMilliseconds, (TIMERPROC)&TimerCallback);
}
}
int main()
{
std::cout << "Main thread is " << std::this_thread::get_id() << std::endl;
g_pMgr = std::make_shared<Manager>();
ProcessDataCheckTimerID = SetTimer(NULL, ProcessDataCheckTimerID, ProcessDataCheckPeriodInMilliseconds, (TIMERPROC)&TimerCallback);
//queue up some dummy data
for (int i = 1; i <= 10; i++)
{
g_pMgr->QueueData(i);
}
//queue a shutdown request
g_pMgr->QueueData(-1);
//fake the application's message loop
MSG msg;
bool shutdown = false;
while (shutdown == false)
{
if (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
shutdown = true;
}
}
return 0;
}

OpenCV VideoCapture does not block on OS X

Short version: on OS X, if I call VideoCapture::read() from a thread other than the main() thread, the call returns immediately instead of blocking till a new frame.
This one works as expect:
void main()
{
VideoCapture vc(0);
Mat img;
While(1) {
vc.read( img ); // blocks till new frame arrives
}
}
This one does not block:
void run( VideoCapture& vc )
{
Mat img;
While(1) {
vc.read( img ); // returns immediately and always returns true
}
}
void main()
{
VideoCapture vc(0);
boost::thread capThread( boost::bind( &run, vc ) );
capThread.join();
}
So in the second version with a separate thread to grab frames, the call to VideoCapture::read(img) returns immediately with return value true, and img is set to the current frame, which means it'll return many duplicate frames.
It's mentioned here:
Problem accessing camera when using Boost thread on OSX
that:
"The OpenCV Camera functions on mac require access to an objective-c NSRunLoop; don't know how to get at one from a new thread though."
Anyone know of a solution to do a blocking frame grab from a thread other than the main() thread?
Alternatively, is there a nice way to discard the duplicate frames?
Thanks
OpenCV doesn't support multi-threading.
Let the main thread capture the frames and do whatever you need to do in the second thread.

WinForm Disappears in Multithreaded C++/CLI Application

I'm currently working on an application that needs to utilize a form to block the user from using the main form for a few seconds. Although running the code on the main thread seems to be okay, the labels on the pop up form don't render for about a second when the form first appears. I thought that if I ran that form on a separate thread, the rendering would be a lot smoother. The rendering is now so smooth that the form disappears immediately after rendering. The timer is set for five seconds, with a label on the screen counting down. Here's the relevant code calling the new thread and form:
System::Void MainScreen::runGame(int playerTurn) {
Thread ^ t = gcnew Thread(gcnew ThreadStart(gcnew MainScreen(),
&MainScreen::showModalDialog));
t->Start();
t->Join();
InitializeDice();
startTimer();
}
System::Void MainScreen::showModalDialog() {
GetReady ^ gr = gcnew GetReady();
gr->showModalPopup();
}
And here's the code inside the form:
public:
GetReady(void)
{
InitializeComponent();
}
System::Void showModalPopup() {
this->Show();
startTimer();
}
private: System::Void timerPrep_Tick(System::Object^ sender, System::EventArgs^ e) {
ts = ts->Subtract(TimeSpan(0, 0, 1));
if (ts->TotalSeconds <= 0) {
finishTimer();
} else {
lblTimer->Text = ts->ToString("mm\\:ss");
}
}
System::Void startTimer() {
array<String ^>^ minSec = gcnew array<String ^>(2);
minSec = lblTimer->Text->Split(':');
ts = gcnew TimeSpan(0, Convert::ToInt32(minSec[0]), Convert::ToInt32(minSec[1]));
Thread::Sleep(900);
timerPrep->Start();
}
System::Void finishTimer() {
timerPrep->Stop();
lblTimer->Text = "GO!!!";
Thread::Sleep(900);
this->Close();
}
My ideal solution would be to use a thread to generate the new form, so that rendering in both the main form and the pop up form is smooth.
Things I've tried:
Moving this->Show() every where I can think to put it.
I've added t->Join() to see if the main thread was trying to bring the main window back into focus. Thread t still executes and the timer still runs appropriately with the Join, blocking user input for five seconds - but there is nothing to block the screen.
I've read a few questions on SO, I think the most relevant one is WinForms multithreading issue - although I feel like that might be overkill for this situation.
If you have any ideas on what I need to do to have smooth rendering for both forms, please let me know. Thanks!
Displaying UI on a worker thread is filled with traps and surprises. The chief problem you are having here is that the thread doesn't pump a message loop. Required first of all to ensure that the window can receive Windows messages and to ensure that the thread doesn't immediately terminate. Beyond Jairo's recommendation to use ShowDialog(), the boilerplate solution is:
System::Void MainScreen::showModalDialog() {
Application::Run(gcnew GetReady);
}
There's more, a thread that displays windows should always be an STA thread. An implementation detail for COM and required to get stuff like the clipboard, drag+drop and shell dialogs operating correctly:
Thread ^ t = gcnew Thread(gcnew ThreadStart(this, &MainScreen::showModalDialog));
t->SetApartmentState(ApartmentState::STA);
t->Start();
And you generally have a Z-order problem with windows that are displayed on the main thread. With a nasty habit of your window disappearing behind a window owned by the main thread. No good solution for that.
The problem is showModalPopup uses Show method instead ShowDialog. The thread starts, shows the form (it doesnt block execution), starts the timer, ends and joins to the main thread. The thread where the form was created has been finished and it's here where the winforms multithreading issues comes.
Start the timer first and then show the modal window with ShowDialog. Something like this:
System::Void showModalPopup()
{
startTimer();
this->ShowDialog();
}

Invoke Windows Form Thread and Sleeping

I have a managed c++ application that I start a new thread to do some stuff and update some text boxes, it loops and sleeps at the end of every loop. Because of it sleeping I needed to have it in a new thread so the UI doesn't crash. Then I realized I need to invoke the thread that created the UI to access the textboxes, but now I'm back in the main thread so the sleeping crashes it. How should I approach this.
private: System::Void buttonStartCamera_Click(System::Object^ sender, System::EventArgs^ e)
{
ThreadStart^ threadStart = gcnew ThreadStart(this, &UserInterface::SetText);
Thread^ newThread = gcnew Thread(threadStart);
newThread->Start();
}
void SetText()
{
if (this->textBoxCameraOneX->InvokeRequired)
{
MyDel^ del = gcnew MyDel(this, &UserInterface::SetText);
this->Invoke(del);
}
else
{
int count = 0;
srand (time(NULL));
for (count = 0; count < 20; ++count)
{
for each (Camera^ camera in cameraList)
{
textBoxCameraOneX->Text = count.ToString();
}
Sleep(300);
}
}
}
The best option is likely to refactor this so your Sleep doesn't occur within the SetText method. Your background thread could use a separate method that performs the sleep, and then invokes the proper method to set the text (for one text box at a time) in a loop.
In general, you should keep the methods you use with Control::Invoke as short as possible - they should only include the logic required for your UI work, and not the other functionality.
That being said, in this case, it seems like a System::Windows::Forms::Timer would be more appropriate. You could set the interval to 300, and update a text box one at a time in the timer's Tick event.

Resources