Wieso lassen so viele Programme den Benutzer so lange warten?



  • Es geht ja auch ganz billig 😉

    Bei QT einfach

    QCoreApplication::processEvents();
    

    in die Schleife der aufwendigen Berechnung setzen. Schon wird die Ereignisschlage der GUI wieder bearbeitet und die GUI verharrt nicht ohne Reaktion.



  • Hallo,

    Mann, was hast Du denn für Probleme? Wer oder was lässt Dich denn so lange warten? Was für lahme Kisten setzt Du denn ein?

    Mal eine andere Geschichte die dazu passt:

    Vor vielen Jahren (OK ich geb's zu es waren ein paar mehr) habe ich in meinem (damals) jugendlichen Leichtsinn ein Programm geschrieben um die Fakultät von 1000000 zu berechnen. Mich hat es einfach geärgert, daß mein Taschenrechner ab 79 nur noch Error geliefert hat.

    Auf das Ergebnis habe ich 7 Tage gewartet. Habe mal soeben spaßeshalber das gleiche mit meiner aktuellen Maschine ausprobiert. Was soll ich sagen: Das Ergebnis wurde schon geliefert, da hatte ich die Entertaste zum Starten des Programms noch nicht richtig losgelassen. Ich glaubte zuerst an einen Fehler und habe mir dann extra meine Aufzeichnungen von damals aus dem Archiv geholt und verglichen. Es war exakt das gleiche Ergebnis.

    Jetzt beschwer dich bloß nicht nochmal über Deine lahme Krücke. Du weißt nicht, was eine lahme Krücke ist.

    mfg Martin


  • Mod

    Hast du auch das gleiche Programm benutzt? Die Geschichte klingt nicht sehr glaubwürdig, kein Rechner sollte jemals mehrere Tage benötigen, um seinen gesamten Hauptspeicher mit signifikanten Stellen von 1000000! zu füllen. Eigentlich sollte sich der Zeitbedarf sogar so ungefähr die Waage halten über alle Epochen hinweg, da die Zeit wichtig ist, in der der Rechner Daten von der Länge seines Hauptspeichers verarbeiten kann. Und falls es nur auf kleine, feste Anzahl Stellen signifikant sein soll, schafft das sogar ein Computer aus den 80ern in Sekunden bis Minuten.



  • Vielleicht hat er den rekursiven Algorithmus aus der Mottenkiste geholt und der Compiler konnte ihn nicht auflösen.

    Edit: Wobei das Ding dann ne Menge Stack gebraucht hätte. 🤡



  • SeppJ schrieb:

    Hast du auch das gleiche Programm benutzt? Die Geschichte klingt nicht sehr glaubwürdig, kein Rechner sollte jemals mehrere Tage benötigen, um seinen gesamten Hauptspeicher mit signifikanten Stellen von 1000000! zu füllen. Eigentlich sollte sich der Zeitbedarf sogar so ungefähr die Waage halten über alle Epochen hinweg, da die Zeit wichtig ist, in der der Rechner Daten von der Länge seines Hauptspeichers verarbeiten kann. Und falls es nur auf kleine, feste Anzahl Stellen signifikant sein soll, schafft das sogar ein Computer aus den 80ern in Sekunden bis Minuten.

    So Du glaubst mir nicht?

    Nun gut ein paar mehr Infos:

    Am großen "Computer-Bild" Vergleichstest nahmen teil:

    • CBM 3032 - 6502 8-Bit CPU - 1 Kern - 1 Thread - 1 MHz Takt - 32 KB RAM - Commodore Basic - Baujahr ca. 1978
    • Dell Vostro 460 - i7-2600 64-Bit CPU - 4 Kerne - 8 Threads - 3,4 GHz Takt - 16 GB Ram - Borland C++ 5.02 - Baujahr 2011

    Das Programm hat natürlich nicht die Fakultät von 1000000 auf alle ca. 5,5 Mio Stellen berechnet, dazu wäre der alte Rechner ohne Festplatte gar nicht in der Lage gewesen.

    Den BASIC Quelltext von damals habe ich nicht mehr, den von gestern gibt es hier:

    #include <stdio.h>
    #include <math.h>
    
    int main( void )
    {
    	double			mantisse = 1.0;
    	unsigned long	exponent = 0;
    	long			i;
    	int				exp;
    
    	for( i=2; i<=1000000; i++ )
    	{
    		mantisse *= i;
    
    		exp = log10( mantisse );
    		if( exp )
    		{
    			exponent += exp;
    			mantisse /= pow10( exp );
    		}
    	}
    
    	printf( "%f %ld\n", mantisse, exponent );
    
    	return 0;
    }
    

    Mit den 7 Tagen, muß ich zugeben kann es schon sein, daß ich ein wenig übertrieben habe. Es ist ja schon viele Jahre her. Es waren aber auf jeden Fall mehrere Tage.

    mfg Martin



  • Die BilligeAntwort schrieb:

    Es geht ja auch ganz billig 😉

    Bei QT einfach

    QCoreApplication::processEvents();
    

    in die Schleife der aufwendigen Berechnung setzen. Schon wird die Ereignisschlage der GUI wieder bearbeitet und die GUI verharrt nicht ohne Reaktion.

    Wenn die Funktion das tut, was ich ihrem Namen nach vermute, handelt man sich überall Reentrancy-Probleme ein.



  • µ schrieb:

    Wenn die Funktion das tut, was ich ihrem Namen nach vermute, handelt man sich überall Reentrancy-Probleme ein.

    Das sieht auch für mich wie das Pendant zum berüchtigten Application.DoEvents() aus 😃 Ein Hoch auf die gefakte Parallelität.



  • GPC schrieb:

    µ schrieb:

    Wenn die Funktion das tut, was ich ihrem Namen nach vermute, handelt man sich überall Reentrancy-Probleme ein.

    Das sieht auch für mich wie das Pendant zum berüchtigten Application.DoEvents() aus 😃 Ein Hoch auf die gefakte Parallelität.

    Genau das.
    Mein Vorgänger hat überall Application.DoEvents() verwendet. Auch in DLLs zur Hardwareansteuerung. Ich bin diesem Menschen nie begegnet und trotzdem hasse ich ihn 😉



  • µ schrieb:

    Die BilligeAntwort schrieb:

    Es geht ja auch ganz billig 😉

    Bei QT einfach

    QCoreApplication::processEvents();
    

    in die Schleife der aufwendigen Berechnung setzen. Schon wird die Ereignisschlage der GUI wieder bearbeitet und die GUI verharrt nicht ohne Reaktion.

    Wenn die Funktion das tut, was ich ihrem Namen nach vermute, handelt man sich überall Reentrancy-Probleme ein.

    Ich habe es gerade getestet.
    Ich weiß nicht wieso es so funktioniert aber ein auslösendes Signal startet eine Methode die sich noch in einer Berechnung befindet erst dann erneut, wenn sie abgearbeitet ist bei Qt. Es wird auch maximal ein weiter Aufruf gespeichert.

    Wenn also während der Ausführung ein Signal entsteht dass die selbe Methode nochmal aufgerufen werden soll, passiert so lange nichts, bis die Methode abgearbeitet ist. Der Aufruf findet erst danach statt. Aber auch nur einmal, egal wie viele Signale inzwischen produziert worden sind.

    Ich habe es mit Qt 4.7.4 getestet.



  • Nachtrag:

    Es scheint irgendwie betriebsystem abhängig zu sein. Nur bei Windows 7 habe ich keine Selbstaufrufe während die Methode noch läuft, bei Windows XP schon.
    Also QCoreApplication::processEvents(); vorsichtig verwenden 😉



  • Um nochmal auf das Grundlegende Thema zurück zu kommen:

    Es bietet sich halt oft an, längere Operationen nicht in Asynchron auszuführen. Zum einen wie schon genannt, da es die Entwicklung vereinfacht, zum anderen aber auch, da es für den Benutzer am Ende egal ist, ob er die Anwendung nicht verwenden kann, weil sie für den Zeitraum nicht reagiert, oder weil die relevanten Steuerelemente gesperrt sind.


  • Administrator

    inflames2k schrieb:

    ..., zum anderen aber auch, da es für den Benutzer am Ende egal ist, ob er die Anwendung nicht verwenden kann, weil sie für den Zeitraum nicht reagiert, oder weil die relevanten Steuerelemente gesperrt sind.

    Würde ich so nicht sagen. Die meistens wissen es nur nicht, dass es auch schneller gehen würde und nehmen es dann halt als ein Ärgernis hin.

    @Eisflamme,
    Mach einfach mal ein paar Beispiele durch, was Multithreading betrifft und dann wirst du schnell mal begreifen, wieso dies nicht alles so einfach ist. Ich habe gerade eben in Android was machen müssen, wo Bilder asynchron aus dem Inet geladen werden und auch zum Teil im Voraus. Wenn der User zum nächsten Bild will, musst du prüfen, ob dieses womöglich bereits schon geladen wird oder schon geladen wurde oder noch gar nicht in Auftrag gegeben wurde. Oder gab es einen Fehler und sollte nochmals ausgeführt werden? Und wie behandelst du Fehler in einer solche Ausführung? Wie meldest du sie dem Benutzer? usw. usf.
    Multithreading verkompliziert das Problem um ein Vielfaches.

    Und nicht zu vergessen sind auch solche Dinge:
    http://magazin.c-plusplus.net/artikel/Der%20Dreisatz%20l%FCgt

    Nicht alles lässt sich parallelisieren.

    Grüssli



  • die Frage ist aber, wie viel vom Parallelisierungsproblem auf die Kappe der Programmiersprachen selbst geht.

    Programmiersprachen wie C++ stammen aus Zeiten, als Parallelisierung noch nicht das Thema war. Ergo keine optimale Formalisierung von nebenläufigen Vorgängen.

    ich kann mir vorstellen, daß sich das in Zukunft nolens volens ändern wird. Sprachmittel zur einfachen Modellierung von nebenläufigen Prozessen werden vielleicht mal das feature sein, so wie heute Klassen und geschweifte Klammern. erlang fällt mir hier spontan ein.



  • Tja, die perfekte Art (sofern sie exisiert) parallele Ausführungsmöglichkeiten zur Verfügung zu stellen ist halt (noch?) nicht gefunden worden.

    Ist aber ein aktives Forschungsgebiet.



  • !rr!rr_. schrieb:

    die Frage ist aber, wie viel vom Parallelisierungsproblem auf die Kappe der Programmiersprachen selbst geht.

    Programmiersprachen wie C++ stammen aus Zeiten, als Parallelisierung noch nicht das Thema war. Ergo keine optimale Formalisierung von nebenläufigen Vorgängen.

    ich kann mir vorstellen, daß sich das in Zukunft nolens volens ändern wird. Sprachmittel zur einfachen Modellierung von nebenläufigen Prozessen werden vielleicht mal das feature sein, so wie heute Klassen und geschweifte Klammern. erlang fällt mir hier spontan ein.

    Gabs alles Schon in Lisp. Ada faellt mir ein. Haskell hat interessante Ansaetze. Und zu guter Letzt: Vhdl bzw. FPGAs.



  • immer gibt es alles schon Jahrzehnte vorher in lisp ... so macht das Diskustieren keinen Spaß 😃



  • Dravere schrieb:

    @Eisflamme,
    Mach einfach mal ein paar Beispiele durch, was Multithreading betrifft und dann wirst du schnell mal begreifen, wieso dies nicht alles so einfach ist.

    Also ich muss aber sagen, mit std::future und std::async geht das meiste schon ganz nett, solange man keinen sehr abhängigen Algorithmus hat. (Was bei Applets und Bildern ja nicht der Fall ist.)
    Wahrscheinlich hatten alle anderen Sprachen das schon lange, aber ich gebe die Hoffnung nicht auf, dass der C++11 Standard da etwas an der Schraube dreht. Ich jedenfalls werde mir jetzt öfter Gedanken machen, ob man etwas nicht parallelisieren kann.



  • inflames2k schrieb:

    Es bietet sich halt oft an, längere Operationen nicht in Asynchron auszuführen. Zum einen wie schon genannt, da es die Entwicklung vereinfacht, zum anderen aber auch, da es für den Benutzer am Ende egal ist, ob er die Anwendung nicht verwenden kann, weil sie für den Zeitraum nicht reagiert, oder weil die relevanten Steuerelemente gesperrt sind.

    falsch. wenn eine anwendung nicht mehr reagiert - also die gui nicht mehr neu gezeichnet wird, z.b. wenn man das fenster verschiebt - nimmt er an, die anwendung ist abgeschmiert.

    unfassbar dass im jahre 2012 offenbar immer noch leute single threaded GUIs schreiben.



  • lolhehe schrieb:

    unfassbar dass im jahre 2012 offenbar immer noch leute single threaded GUIs schreiben.

    Die GUI selbst ist doch eigentlich immer singlethreaded. Nur gewisse langdauernde Arbeiten werden ausgelagert.
    Oder gibt es ernstzunehmende GUI toolkits, bei denen die grafische Oberfläche selbst in mehreren threads läuft?



  • lolhehe:
    Ich muss sagen, das wundert mich genau auf der Ebene eben auch... und ich habe jetzt selbst ein paar asynchrone Dinge implementiert und finde das in den meisten Fällen überhaupt nicht schlimm.

    Einfach einen Workerthread nehmen und dem n Task zuteilen und bei Abarbeitung eben das Ergebnis die GUI schreiben. Wechselt Benutzer etwas oder tut etwas, weswegen der Task abgebrochen wird, wird der Task abgebrochen, gut ist. Und wenn man mit Ergebnissen weiterarbeiten möchte bzw. der User das können soll, blockiert man die Weiterarbeitung, sodass nicht gleichzeitig ein Task und das Arbeiten mit den Ergebnissen geschehen kann. Und soll es das, identifiziert man auch für Benutzer die Tasks eindeutig, damit er das jeweilige Ergebnis auswählen kann.

    Aber irgendwie scheint das nicht so der Stand zu sein, keine Ahnung. Ich merk ja, das kann schnell kompliziert werden, aber das sehe ich mehr bei Echtzeit-Interaktion von vielen Threads, die unterschiedliche Dinge tun mit sehr vielen Abhängigkeiten, als bei ner GUI, wo man Tasks auslagert.


Anmelden zum Antworten