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


  • Qt Champions 2016

    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();
    }
    


  • @haxxe

    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);
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.