Unsolved need ideas: using threads for can sending?
-
hi,
i have a function which sends 1700 can frames per sec. (34 frames after every 20ms).
but there is one problem: the GUI gets kinda laggy/unresponsive(on raspberry pi) because the GUI thread is working on it?
i already tried out threads with qfuture and qconcurrent, but my function is pretty messy and the compiler complains about this:error: invalid use of non-static member function
so, do i really need threads or is there another, good way to keep the gui fast and keep my function running?
maybe i also need threads because i want to receive frames, too.
what do you think?
greetings -
Hi
Yes, if you have a heavy function in the main thread.
If it stays long in there, you are strangulating the event loop.
(the exec() u seen in main.cpp)to solve this, its a good idea to use a worker object and run in a thread.
https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/-
maybe i also need threads because i want to receive frames, too.
Yes, as while sending, it will not be able to read anything otherwise. -
error: invalid use of non-static member function
Hard to guess at without the code.
It most likely involves something u flagged as static.
Like a static function.
-
-
@haxxe
Hi,create one more thread object(Worker Thread) and whatever the functionality regarding sending the frame is assign to this thread. dont use UI Thread for other activity like sending the huge data.
-
ok thanks i'll check the links.
i've read very often, that one shouldnt use qthread, because qtconcurrent seems to be better?
but i'll try it with qthread.EDIT: ok, i got the basics running.
what now? do i have to copy my functions over to the worker class and call it within them?
for example i do have this function:void MainWindow::pushSingleDataToSlave() { QByteArray payload =""; QCanBusFrame frame; unsigned int frameID = 0; int led_nr = ui->spinBox_ledNr->value(); if(led_nr >= LEDs_TOATL_COUNT) return; // generate frame id frameID = generateFrameId( ID_OP_GRAY_SCALE_DATA, led_nr); payload.append((uint8_t)(ledGrayscale[led_nr]&0x00FF)); payload.append((uint8_t)((ledGrayscale[led_nr]&0xFF00)>>8)); frame.setFrameId(frameID); can->writeFrame(frame); }
in mainWindow, how do i put this on a thread?
EDIT: is it just enough to make an object of MainWindow?
void Worker::process(){ //allocate ressources using new here qDebug("Hello World!"); MainWindow ui; ui.initCanBus(); ui.pushSingleDataToSlave() emit finished(); }
-
Hi,
Create one class inherit from QThread,//WorkerThread.h
Class WorkerThread :public Qthread
{public:
void run();
void sendFrame();
};//WorkerThread.cpp
WorkerThread::run()
{
sendFrame();
}
WorkerThread::sendFrame()
{
//sending Functionality here
}//in mainWindow Class
WorkerThread *wThread = new WorkerThread;
wThread->start(); // it calls run method -
thanks! my function is kinda komplex but ill try it soon :)
-
Hi @haxxe,
you're really sending 1700 CAN frames per second? Which bitrate are you using? And how is which CAN adapter connected? (AFAIK Raspberry don't have CAN onboard...)
In your send function, your creating a payload but do not assign it to the CAN frame, is this correct?
Also, you can simplify your function like this:
void MainWindow::pushSingleDataToSlave() { int led_nr = ui->spinBox_ledNr->value(); if (led_nr >= LEDs_TOATL_COUNT) return; // generate frame id quint32 frameID = generateFrameId( ID_OP_GRAY_SCALE_DATA, led_nr); QByteArray payload; payload.append((uint8_t)(ledGrayscale[led_nr]&0x00FF)); payload.append((uint8_t)((ledGrayscale[led_nr]&0xFF00)>>8)); const QCanBusFrame frame(frameID, payload); can->writeFrame(frame); }