PDA

View Full Version : GUI Thread getting no time to process



steg90
8th May 2007, 14:47
Hi,

I have created a worker thread from my main gui, the worker thread just does some simple processing and emits a signal to the gui which then processes the data it has been sent. But the worker thread is taking up most of the time available and giving the gui thread no time to do anything. The worker just sleeps for one millisecond ( msleep(1) ), but it has to be this quick as it is responsible for reading CAN traffic off a vehicle, is there anyway of allowing the gui to have more time without changing the msleep?

Regards,
Steve

wysota
8th May 2007, 14:51
Can we see the code of the thread and how you start it?

marcel
8th May 2007, 15:01
Oh my God...
I already told you... Emitting a signal from a thread = receiving an event in the interface.
The interface receives an event every milisec, so, unless you have a pretty good computer, I doubt the event handler will be able to process them all as they come, meaning processing 1000 events in 1 second.

EDIT: I'm not even sure that all 1000 events are posted all in 1 sec. There might be some delays.

regards

steg90
8th May 2007, 15:02
Hi,

Yes of course, here is how I create the thread within the main gui :



if( !m_pCanReadThread->isRunning() )
m_pCanReadThread->start(QThread::IdlePriority);


Where m_pCanReadThread is of CanRead object shown below :



class CanRead : public QThread
{
Q_OBJECT
public:
CanRead();
public:
void run();
signals:
void datareceived( int nCount );
};




void CanRead::run()
{
static volatile int nCount = 1;
while( nCount < 10000 )
{
// read can data - removed for clarity
msleep(10);
emit datareceived( nCount - 2 );
nCount++;
}
}


The datareceived signal is emitted to the main gui which just updates a tableview.

Thanks,
Steve

steg90
8th May 2007, 15:12
So this is impossible?

I do this in one of my MFC applications and the gui is not 'hogged'?

Regards,
Steve

marcel
8th May 2007, 15:16
Not impossible.
One way is to buffer incoming data for, let's say for 500 milisecs( or less ), and then send them all to the GUI in one step and let it update the table view.

Maybe the guys have other, better, solutions.

gfunk
8th May 2007, 17:59
Sounds way too frequent. If your GUI thread is being overloaded, maybe you should just let it ignore signals and continuously process the data to be displayed at its own pace.

marcel
8th May 2007, 18:10
But wouldn't it skip some of the data this way?
Buffering the data in the worker thread and sending a buffer every 500 ms would make items appear rarely but they will appear all.

Regards

wysota
8th May 2007, 19:33
I'd suggest connecting the signal to a slot which will simply queue the changes and then perform a periodical update of the view that contains all the changes since the last update. And if you're using the model-view approach, avoid inserting one item at a time or block signals from the model during all insertions.

steg90
9th May 2007, 08:44
Hi,

Some interesting suggestions.

One I'd like to know is how do you block the signal from the model when I'm inserting data? Do I disconnect the signal? The model does emit a signal to my view to tell me that the table needs updating. What I have in my model now is it gets data, stores this in a structure and passes this structure back to the view using a signal, the view then inserts this data into the table and scrolls it. I still have to have a sleep of 10 milliseconds in order for the gui to keep up.

The code below shows the method that gets signalled in the view to update the table :



void CanView::scrolltable( int nCount, CANDATA* pData )
{
for( int i = 0; i < CANAMOUNT; i++ )
{
m_ptreeModel->setCanData( pData[i].m_strId );
m_ptreeModel->setCanData( pData[i].m_strTime );
m_ptreeModel->setCanData( pData[i].m_strData );
QString strCount;
strCount.sprintf( "%i", nCount );
m_ptreeModel->setCanData( strCount );
nCount++;
}

QModelIndex index = m_ptreeModel->index( nCount, 0 );
ui.tableView->scrollTo( index );
}


This is signalled every 10 milliseconds from the worker thread which just basically now reads CAN data into a structure. The setCanData method is a public method within the model :



void DATreeModel::setCanData( const QString& strData )
{
QModelIndex index;
beginInsertRows(index, 1, 1);
m_Data.append(strData);
endInsertRows();
}


As you can see, this inserts one item of data at a time, maybe the structure should be passed across here? Don't know if this would be quicker or not, the method would change to :



void DATreeModel::setCanData( CANDATA* pData, int nAmountData, int nCount )
{
QModelIndex index;
beginInsertRows( index, 1, nAmount );
for( int i = 0; i < nAmount; i++ )
{
m_Data.append( pData[i]->m_strId );
m_Data.append( pData[i]->m_strTime );
m_Data.append( pData[i]->m_strData );
QString strCount;
strCount.sprintf( "%i", nCount );
m_Data.append( strCount );
}
endInsertRows();
}



m_Data is just a QList<QString> container.

Kind regards,
Steve

marcel
9th May 2007, 08:57
One I'd like to know is how do you block the signal from the model when I'm inserting data? Do I disconnect the signal?
Use model->blockSignals( true ).
When you want to activate them again use model->blockSignals( false ).

steg90
9th May 2007, 09:29
Hi,

Turning off the signals AND inserting more than one item at a time in the model has speeded this up no end, I can now set the thread to just sleep for one millisecond and the GUI still got time to process. Many thanks to all!! :D :D :D

Regards,
Steve