E-Mail-Versand (Indy 9) macht das Programm unbedienbar
-
Hallo Leute,
ich verwende BCB 5.0 Pro und Indy 9.
Das Problem ist, dass während des Senden von E-Mails meine Applikation unbedienbar bleibt.
Ich habe das Senden der E-Mails schon in einen Thread ausgelagert, und zwischendurch "ProcessMessages()" verwendet, ohne Erfolg.Das Senden wird im Thread "Execute()" in Verbindung mit "Syncronize()" aufgerufen.
Hat vielleicht jemand von euch das gleiche Problem gehabt?
-
Hallo
Ich habe auch Indy9-Mailversand in einem Thread laufen und kann die von dir berichtete GUI-Blockade nicht nachvollziehen. Denn genau das sollen Threads verhindern. Du must schon mehr von Aufbau deines Mailversands erklären, bevor wir dazu etwas konkretes sagen können.
bis bald
akari
-
Danke, das hat sich erledigt.
Ich habe rufe jetzt die Versand-Funktion ohne "Syncronize()" auf.
Die "Syncronize()" unterbricht ja den VCL-Hauptthread. Ich muss nur aufpassen,
dass das Hauptprogramm und der Thread nicht gleichzeitig auf Datenelemente
zugreifen.
-
Hallo
Das Synchronize sollte ja auch nur ab und zu vom Thread aus aufgerufen werden, um Daten auszutauschen (in der Regel eine Fortschritts-Anzeige aktualisieren). Das sollte aber nur so oft wie absolut notwendig geschehen, denn Synchronize bremst sowohl Thread also auch GUI. Kann es sein das du nur viel zu häufig und unnötig Synchronize aufrufst?
bis bald
akari
-
Ja, ich habe "Syncronize()" jedes mal aufgerufen, und darin die Versand-Funktion:
void __fastcall E_Mail_versenden::Execute() { // Prüfen, ob der Thread eine Aufforderung zum Terminieren bekommen hat // ===================================================================== if(!Terminated) { Sycronize(&E_Mail_senden); } }
Gruß
sonic
-
Hallo
Und genau das ist falsch, denn damit befindest du dich quasi permanent im Synchronize, und der einzige Vorteil von Threads ist zunichte. Der Aufbau sollte so aussehen (Pseudocode). Das Beispiel geht davon aus, das es eine externe Warteschlange gibt (in die von außen die zu versendenden Mails eingetragen werden, ohne weiteres Synchronize) und eine interne (in die nur der Thread selber zugriff hat)
Thread::Execute() { while (!Terminated()) Synchronize(&Warten); Wenn MailsInInternerWarteschlangeVorhandenSind { MailsInInternerWarteschlangeSenden(); InterneWarteschlangeLeeren(); Synchronize(&Fertig); } else { Sleep(100ms); // Oder mehr } } Thread::Warten() { // Eventuell GUI aktualisieren Wenn MailsinExternerWarteschlange { MailsVonExternNachInternVerschieben(); } } Thread::Fertig() { // Eventuell GUI aktualisieren }
Ein anderes Herangehen wäre, den Thread komplett in ein eigenes Metaobjekt zu kapseln, das nichts weiter tut als die eigentliche Warteschlange nach innen und außen zu repräsentieren und auch zu kapseln. Sobald eine oder mehrere Mails eingetragen wird, startet das Container-Objekt automatisch den passenden Thread, der die Mail(s) versendet und sich dann wieder beendet, wenn die Warteschlange leer ist. Sollten neue Mails eingetragen werden, während der Thread noch läuft, wird die Warteschlange im laufenden Thread ergänzt. (Thread muß sich trotzdem mit Warteschlange und GUI synchronizieren). Vorteil : Du hast keinen Dauerthread der meistens eh nur im Standby wartet, und der Versand beginnt sofort und nicht erst nach maximal 100ms.
bis bald
akari
-
Vieln Dank für den Beispiel. Hat mir sehr weitergeholfen.
Und schönes Wochenende
-
*Lesezeichen setz*
Ihr wisst ja gar nicht wie viel MIR das geholfen hat
-> *C++ Builder rauskram*