PDA

View Full Version : deleting QListItemWidget crashed which was triggered by another thread



zeopha
2nd August 2008, 08:17
I created QMainWidget which contains a QListWidget to show log information coming from a socket thread which processed network business. showing log info slots (addLogInfo(const QString &log)) was triggered by a signals in that socket thread . a log item will be created and added to QListWidget every 20 milliseconds.

the signal and the slot was connected in the socket thread's run function with Qt::DirectConnection:

connect(this, SIGNAL(addLogInfo(const Log::LogLevel &, const QString &)), parent, SLOT(addLogInfo(const Log::LogLevel &, const QString &)), Qt::DirectConnection);

here, "this" is pointed the socket thread object, "parent" is a QMainWidget pointer which pointed to GUI which contained the QListWidget.

in such partern with Qt::DirectConnection, I think that the addLogInfo slot was executed in the socket thread(am I right?). In fact, What I want really is that the slot was executed by QMainWidget thread itself which can be done through Qt::QueuedConnection. But when I set connect function with Qt::QueuedConnection, it will complain:
"QObject::connect: Cannot queue arguments of type 'Log::LogLevel'
(Make sure 'Log::LogLevel' is registered using qRegisterMetaType())

But I don't know how to register my user-defined type Log::LogLevel, such statement:
qRegisterMetaType<Log::LogLevel>("LogLevel") won't work. Log is:
class Log
{
private:
Log();
~Log();
public:
enum LogLevel {Debug=0, Info=1, Warning=2, Error=3, Fatal=4};
};

when QListWidgetItem number in QListWidget is more than a threshold (such as 50), QMainWidget will delete the first QListWidgetItem in QListWidget through the statement "delete lsgLogInfo->item(0)" located in the slot.

After deleting item several times, the program will crash with following gdb info:
ASSERT failure in QVector<T>::operator[]: "index out of range", file ../../include/QtCore/../../src/corelib/tools/qvector.h, line 324

In fact , I inserted a statement "printf("count=%d\n", ui.lstLogInfo->count());" which printed the count is the threshold plus one. So , the deleted index equal to 0 will not be out of range. But the crash really happened.

anybody can help me?
any help will be appreciated!
thx!

caduel
2nd August 2008, 09:14
i) indeed, with DirectConnection the call will be executed in the wrong thread. Not good

ii) you have to use qRegisterMetaType.
Probably as

qRegisterMetaType<Log::LogLevel>("Log::LogLevel");
(i.e. you have to include the namespace/class name, I think).

If this does not fix it:
Could you be more elaborate on what "won't work" means?

HTH

zeopha
2nd August 2008, 11:16
U r so kind!
thank u very much!

It succeeds without any complains, even no crash which I mentoned above after registering my data type according to your suggestions.

So, I think that crash was caused by the incorrect usage of the connect between slots and signals. that is, thread used functions which was located in other threads, which will cause some uncertain results.

Again, thank u very much!



i) indeed, with DirectConnection the call will be executed in the wrong thread. Not good

ii) you have to use qRegisterMetaType.
Probably as

qRegisterMetaType<Log::LogLevel>("Log::LogLevel");
(i.e. you have to include the namespace/class name, I think).

If this does not fix it:
Could you be more elaborate on what "won't work" means?

HTH