Seite 1 von 1
GUI friert ein
Verfasst: 19. Dezember 2011 09:39
von reinki0013
hallo zusammen,
ich habe ein programm, welches dateien an einen ftp-server sendet.
in diesem zuge habe ich auch einen fortschrittsbalken gemacht. ich habe jetzt allerdings das problem, z.b. mit windows 7 friert mir die GUI ein sobald ich außerhalb des Programms wo hinklicke. Bei einem weiteren klick kommt sofort die meldung (keine Rückmeldung) und der Inhalt meiner GUI wird weiß...
hat da jemand schon erfahrungen in diese richtung gemacht bzw. kann mir da jemand weiterhelfen?
lg
Re: GUI friert ein
Verfasst: 19. Dezember 2011 10:04
von franzf
Wenn du uns zeigst, wie du es machst (Code!) können wir dir vielleicht sagen, was du ändern kannst, damit es funktioniert.
Da ich nicht weiß, unter welchen Umständen Windows diese Meldung raushaut, kann ich nur in Richtung "du hängst in einer blockierende Funktion" mutmaßen.
Re: GUI friert ein
Verfasst: 19. Dezember 2011 10:26
von reinki0013
hi,
also ich habe einen QTcpSocket und einen QTextStream.
in einer while-schleife schicke ich die daten von meinem QTextStream an meinen QTcpSocket bis nichts mehr im QTextStream drinnen steht.
Währenddessen friert mir dann die GUI ein, wenn ich während dieser Schleife etwas anderes mache bzw. wo anders hinklicke...
hiflt dir das schon weiter?
sonst hier der code von der funktion
Code: Alles auswählen
bool eModem::Send(QString Name, QByteArray data)
{
out << "re\r";
out.flush();
sock.waitForReadyRead(3000); // max. 3 Sekunden warten
QString empfang;
while(!in.atEnd())
{
in >> empfang;
if(empfang == "start")
{
quint32 len = data.size();
qint64 maxlen = len;
qint64 pos = 0;
out << Name << '\0' << len << '\0';
out.flush();
while(len)
{
sock.waitForReadyRead(10000);
in >> empfang;
if(empfang.size() == 0)
return false;
if(empfang == "fin")
pos = maxlen;
else
pos = empfang.toInt();
emit Progress(pos, maxlen);
len = data.size();
if(len > 512)
len = 512;
QByteArray buf;
buf.append(data.constData(), len);
data.remove(0, len);
sock.write(buf);
//out << buf; // out funktioniert nicht wegen TextStream
//out.flush();
sock.flush();
sock.waitForBytesWritten(3000);
}
return true;
}
}
return false;
}
lg
Re: GUI friert ein
Verfasst: 19. Dezember 2011 11:17
von franzf
QIODevice::waitForReadyRead() ist blockierend, deine Gui reagiert nicht. Es steht auch noch ganz klar dabei:
It is useful when writing non-GUI applications and when performing I/O operations in a non-GUI thread.
Also: entweder lagerst du das ganze in nen eigenen Thread aus, oder du nimmst gleich die asynchrone API (also über SIGNAL/SLOT), letzteres wäre die zu bevorzugende Methode.
Du hast auch ganz schön lange Timeouts gesetzt, in jedem Durchlauf der inneren Schleife blockierst du zusammen 13 Sekunden.
Re: GUI friert ein
Verfasst: 19. Dezember 2011 13:10
von GottfriedSp
In der Schleife ist ein
Welcher das Signal zum Slot in das Hauptfenster leitet und damit der Fortschrits-Balken aktualisiert wird (ca. 500ms pro Aktualisierung).
Das Programm funktioniert im Debug-Modus perfekt, allerdings das Release funktioniert nicht.
Bei Windows XP funktioniert sogar das Release noch so einigermassen.
Mit Thread hatten wir es auch schon versucht, welcher bei Windows 7 mit dem Debug-Binaries perfekt funktioniert, allerdings bei Release wird der QMutex irgend wie nicht beachtet oder durchgeführt. (statische QMutex).
Wir haben die 4.7.4 und 4.7.1
Re: GUI friert ein
Verfasst: 20. Dezember 2011 08:13
von reinki0013
Kann uns beiden wer einen Tipp geben?
Re: GUI friert ein
Verfasst: 20. Dezember 2011 10:33
von reinki0013
also ich habs jetzt mal probiert mit QThread - aber da bin ich überfordert...
ich habe jetzt folgendermaßen probiert:
Code: Alles auswählen
bool eModem::Send(QString Name, QByteArray data)
{
QThread *thread = new QThread;
this->moveToThread(thread);
thread->start();
out << "re\r";
out.flush();
sock.waitForReadyRead(3000); // max. 3 Sekunden warten
QString empfang;
while(!in.atEnd())
{
in >> empfang;
if(empfang == "start")
{
quint32 len = data.size();
qint64 maxlen = len;
qint64 pos = 0;
out << Name << '\0' << len << '\0';
out.flush();
while(len)
{
sock.waitForReadyRead(10000);
in >> empfang;
if(empfang.size() == 0)
return false;
if(empfang == "fin")
pos = maxlen;
else
pos = empfang.toInt();
emit Progress(pos, maxlen);
len = data.size();
if(len > 512)
len = 512;
QByteArray buf;
buf.append(data.constData(), len);
data.remove(0, len);
sock.write(buf);
//out << buf; // out funktioniert nicht wegen TextStream
//out.flush();
sock.flush();
sock.waitForBytesWritten(3000);
}
return true;
}
}
return false;
}
das funktioniert aber leider auch nicht - die GUI friert trotzdem ein beim Release...
lg
Re: GUI friert ein
Verfasst: 20. Dezember 2011 11:07
von brax
Du startest zwar jetzt tatsächlich einen Thread, der hat aber nichts mit dem zu tun, was Deine eModem Klasse macht. Du müsstest Deine gesamte eModem Klasse in eine von QThread abgeleitete Klasse überführen.
Aber das ist eigentlich auch gar nicht notwendig. Wie franzf gesagt hat, bietet QTcpSocket ja schon alles, was Du für asynchrone Kommunikation brauchst (über QIODevice). Du musst in eModem auf das readyRead() Signal des Sockets reagieren und erst dann aus dem Socket lesen, wenn es ankommt. Ein Mögliches Timeout solltest Du dann allerdings selbst implementieren über einen QTimer, den Du jedesmal beim Empfangen von Daten killst und nach dem Senden neuer Daten anwirfst. Wenn der Timer irgendwann feuert, kappst Du die Verbindung, damit der Server auch bescheid weiß.
Re: GUI friert ein
Verfasst: 20. Dezember 2011 12:38
von GottfriedSp
Das mit readyRead() funktioniert einwandfrei!
Auf die Einfachsten Dinge kommt man immer zuletzt
