PDA

View Full Version : Problems with threads and windows



SkripT
11th January 2006, 19:00
Hi all, I'm using Qt4 opensource on windows XP. This time I have a serious problem with threads and Windows: the aplicattion consists in a wizard of three pages. The first page the user chooses some parameters. In the second page, I start a thread that makes some process on the images that the user has selected in the previous page. That process consists in rotations and scaleds of the image. I start a thread that process the images in background. When the thread starts or finishes the process of every image it emits a signal and I connect this signal to a slot of the main thread in which I show a message with the result of the process in a QTextEdit Window, and the progress with a progress bar. Well, all goes perfect if I let the pc alone running only this program. The problem comes when, if I minimize the program and I try to do something else, the wizard crashes with a message related to Qtgui4.dll. Moreover, if when the thread is running (is processing the images) I try to scroll the bars of the textedit window, the program crashes too with the same error message :confused: Very strange. The next page of the wizard I make a thumbnailing of the images to see the results: I start a new thread to resize the images and I emit a signal with the thumbnailed image. At the main thread, I connect this signal to a slot that simply fills a QListWidget with the images that receives. Well, my surpise comes when, if I try to move the scrolbars of the QListWidget when the thread is running, the application crashes like before :eek:
I really will be very grateful if someone has the same problem and knows how to solve it or If anyone could tell me if I'm doing something wrong. I think that the code is ok because, as I have said before, if I let the machine running only the apliccation, all goes ok.

thanks.

wysota
12th January 2006, 02:49
Based on your description I have a suspicion that your problem is a quite common one and involves doing gui operations from a worker thread, but I'd like to make sure, so could you please post some code here which you think is relevant for the case? Especially the part which involves interaction between threads.

SkripT
12th January 2006, 11:34
Hi all, I post the code where I interact with the thread that creates the thumbnails of the images becuase the other thread uses a lot of irrelevant functions. The problem with this thread is that if I move the scrollbars of the QWidgetList when the thread is creating the thumbnails (and the main thread updating the list) the program chrashes. That's the code of the 'run' method of the thread:

void CreadorFotosPetitesThread::run()
{
QImage fotoImage;

uint n = llista.count();

for (uint i = 0; i < n && !abortar; i++)
{
if (fotoImage.load(dir + llista[i]))
{
fotoImage = fotoImage.scaled(TAM_ICON_HOR,
TAM_ICON_VER, Qt::KeepAspectRatio,
Qt::FastTransformation);

emit fotoPetitaCreada(fotoImage, i, dir);
}
}

emit fiCreacio();
}
In the method where I call the start function of the thread, I pass the list of files ('llista') and the directory ('dir') which it creates the thumbnails. And the following code is the slot that I connect with the signal 'fotoPetitaCreada' in the main thread:

void PaginaResultats::actualitzarFotosPetitesList(const QImage &fotoImage, int index, const QString &pathDir)
{
QListWidgetItem *fotoPetitaItem = fotosPetitesList -> item(index);

QString pathDirActual = ((DirectoriTreeWidgetItem *)
(subDirsTreeWidget -> currentItem())) -> pathDirectori();

if (!fotoPetitaItem || pathDir != pathDirActual) return;

fotoPetitaItem -> setIcon(QPixmap::fromImage(fotoImage));
}

'fotosPetitesList' is the QListWidget and, before the thread is started, I fill the list to set the text of the QListWidget items with the name of the files and an inicialization icon that will be replaced later with the icon created with the image that provides the thread.

I hope that this will help to find the problem. If there's some question with this code feel free to ask me here. Thanks

jacek
12th January 2006, 15:21
void PaginaResultats::actualitzarFotosPetitesList(const QImage &fotoImage, int index, const QString &pathDir)
You pass a reference to that slot and since that slot is in another thread it will be delivered through an event, but the object to which this reference refers to will be overwritten in the same time by the original thread. This might lead to serious troubles.

Try passing that QImage and QString by value (they use implicit sharing, so there won't be any problems).

SkripT
12th January 2006, 17:44
Yes this could cause an error but I made it this way because if you see the example /examples/threads/mandelbrot passes a reference to the generated image too. This is because the connection between the signals and slots is queued because are different threads, as the documentation explains. This means, I think, that the parameters of the signal are copied in a queue before the slot is called. But depending in the time that the parameters are copied in the queue could cause an error, so why an example of the doucmentation are doing it wrong?:confused:

jacek
12th January 2006, 20:56
Yes this could cause an error but I made it this way because if you see the example /examples/threads/mandelbrot passes a reference to the generated image too.

I've checked that example and Qt sources and it looks like emit makes a copy of those parameters, even when you pass then as a reference.

I hope you have noticed this:

With queued connections, Qt must store a copy of the arguments that were passed to the signal so that it can pass them to the slot later on. Qt knows how to take of copy of many C++ and Qt types, but QImage isn't one of them. We must therefore call the template function qRegisterMetaType() before we can use QImage as parameter in queued connections.

SkripT
13th January 2006, 01:00
Yes, I make a qRegisterMetaType() of QImage and QString before I connect the signal with the slot. Any other suggestion please?

jacek
13th January 2006, 16:02
Did you try to run that application from debugger? Could you post the backtrace?

SkripT
13th January 2006, 18:32
Sorry for my ignorance but could you please tell me how to run the debugger in the commad line to obtain the backtrace? Thanks

jacek
13th January 2006, 19:28
how to run the debugger in the commad line to obtain the backtrace?
If you use MinGW, it should be:C:\...> gdb prog.exe
(gdb) run
<program crashes>
(gdb) bt
<backtrace>
(gdb) quit

SkripT
13th January 2006, 19:34
thanks a lot i'm going to try it.

SkripT
14th January 2006, 00:51
Hi, here's the backtrace as a result of a program crash:

Program received signal SIGSEGV, Segmentation fault.
[Switching to thread -277..........]
0x1012c44b in _size_of_stack_reserve__ ()
and the message from the program drwatson of windows is that the program has made an illegal acess to memory.
As I think, crashes as a result of an overload of the stack. I guess that's because I am working with some QImages at the same time and I think that could be better to define the images in dynamic memory. I will try it.

jacek
14th January 2006, 00:57
Hi, here's the backtrace as a result of a program crash
It's rather short. Wasn't there more output?


As I think, crashes as a result of an overload of the stack. I guess that's because I am working with some QImages at the same time and I think that could be better to define the images in dynamic memory.
AFAIK QImage stores data on the heap.

SkripT
16th January 2006, 11:07
Hi again, gdb alerts me with two warnings that I tried to re-register class QString because I was trying to do a qregistertyper of QString. I have deleted the instruction and seems that the program not crashes, in the short time that I have tested it. Could I think that this was the problem?

jacek
16th January 2006, 18:16
Hi again, gdb alerts me with two warnings that I tried to re-register class QString because I was trying to do a qregistertyper of QString.
That warning comes from Qt itself. If you add "CONFIG += console" to your .pro file, you should be able to see such warnings on the console, without the need of debugger.


I have deleted the instruction and seems that the program not crashes, in the short time that I have tested it. Could I think that this was the problem?
Might be, but it shouldn't crash just because you tried to register something twice.

SkripT
16th January 2006, 18:46
Ok jacek, thanks for tell me how to view the warnings from the console and for all the other suggestions. I will test the program a little more running it with the debugger, hoping that doesn't crash :D