GUI Programmierung

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Wenn Threads richtig angewandt werden, sollte es auch keine Probleme
geben. Leider werden Threads, gerade von Einsteigern, zu oft und
vollkommen falsch angewandt. Hinterher kommen dann die Fragen, bzw.
werden nicht vorhandene Bugs in PB gemeldet. Deshalb sollten sich
Einsteiger lieber erstmal mit Callbacks und Timern auseinandersetzen, diese
bewirken oftmals dasselbe, ohne nicht nachvollziehbare IMAs zu erzeugen.

meine Bilddazu
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
TWELVE
Beiträge: 72
Registriert: 01.04.2007 18:33

Beitrag von TWELVE »

Hallo zusammen,

ist schon eine Weile her, aber trotzdem noch aktuell.Habe den Code aus bestimmten Gründen nicht angefaßt und war vor ca. 2 Wochen "genötigt", dies zu tun.Mein Progrämmchen hat nützliche Dienste erwiesen, aber es gab und gibt natürlich immer etwas zu verbessern.Und weil alles wesentliche bereits in diesem Thread steht, bleibe ich auch direkt hier und mach keinen neuen auf.

Ich habe mir ein neues GUI gebaut ( war notwendig, das alte war zuvoll gepflastert...aus Zeitgründen), neue Funktionen hinzugefügt und alte Routinen überarbeitet oder eliminiert.Einiges davon ne "Katastrophe", nun ich wußte vieles einfach nicht besser und bin trotzdem stolz, das ich von 0 auf 100 ein Ergebnis mit PureBasic hervorgebracht habe.Seitdem habe ich einiges dazugelernt und lerne natürlich immer noch.

Im Verlauf der Überarbeitung habe ich auch den Fehler gefunden, warum das GUI ( die Buttons, die Menus...) nicht so wirklich toll reagiert hat ( mußte zweimal klicken usw.)

Wen es interessiert: ich hatte in der Event Loop zuviel zusätzlichen Code drin, der den Update einiger Gadgets erledigt hat."Lustigerweise" bin ich darauf gekommen, weil man mir hier im Forum ( und auch anderswo) von der Verwendung von Threads abgeraten hatte.Also habe ich krampfhaft versucht, das Meiste im Main unterzubringen und Thread zu vermeiden.
Nachdem ich diesen Code in einen separaten Thread ausgelagert hatte, funktionierte das GUI wieder so wie ich mir das vorstellte.

Ich habe also einen Thread, der Gadgets updatet.Das geht sicher eleganter oder sicherer, ich weiß nur nicht wie.

Irgendwann gings nicht mehr ohne Threads, da ich nunmal ein paar Sachen parallel machen muß und ich nicht wußte, wie ich das ohne Threads bewerkstelligen konnte.Oft sehe ich auch WINAPI Codeschnippsel, aber ehrlich gesagt wollte ich das erstmal ohne WINAPI hinbekommen.

Ich verwende seit letztes Jahr bis zu 4 Threads in meinem Progrämmchen gleichzeitig und lustigerweise hat das bis jetzt keine Probleme verursacht, obwohl ich nur experimentell mit Mutexes gearbeitet habe.

So, nun zu meinem aktuellen Problem:

Nachdem ich das Programm die ganze Zeit ohne Probleme direkt im PB IDE/Debugger bearbeitet und ausgeführt hab, stürzt es nun - als eigenständige exe gespeichert und gestartet - sporadisch ab.

Windows hat ein Problem festgestelllt blabla und Programm muß beendet werden.Exception Code ist 0xC0000005, was wohl Access Violation bedeutet.Die Fehleradresse ist - zumindest mit einer bestimmten exe Version - immer die gleiche.Also im Moment ist dies z.B. 0x00017531.Ich nehme an, dies ist der Offset von da aus, wo das Programm im Speicher zu liegen kommt ( Base Image?).

Um auszuschließen, das es was mit dem Rechner zu tun hat, habe ich das Programm auf einem anderen Rechner getestet.Hier kam der Fehler sogar noch öfter und schneller.Mag daran liegen, das der zweite Rechner nen Dual Core ist ( Pentium M vs. Core 2 Duo).

Jaja..ich weiß..jetzt kommt gleich wieder: das haste nun von Deinen Threads...:D

Die Fehleradresse ist ja ein guter Hinweis, ich müßt jetzt "nur noch2 herausbekommen, was auf dieser Adresse zu liegen kommt, damit ich den Fehler beseitigen kann.Mit dem IDE Debugger bin ich da nicht wirklich weitergekommen.Ganz einfach deshalb, weil der Fehler nicht auftritt, solange der Debugger mitläuft..:-((

Ich habe diesen Thread, der mein GUI updatet in Verdacht.Wenn ich ihn testweise nicht starten lasse, tritt das Problem nicht auf.Dies ist allerdings nicht so einfach zu beweisen, da der Fehler auch mit Thread nicht vorhersagbar auftritt.

Desweiteren habe ich nun Mutexe eingebaut, um alle Variablen zu schützen, die von mehreren zugegriffen werden.

Compiliere ich den Code als thread-safe, tritt der Fehler nicht mehr auf.Allerdings wird das Program auch merklich langsamer dadurch.

- wie kann ich dem Problem mit dem Crash auf die Spur kommen...?

- gibt es irgendwo eine Art "Best Practices" für die Thread-Programmierung...?

Die Hilfe zu den Threads ist mehr als dürftig und meine Recherche in den Foren hat nicht wirklich viel geholfen.Ich habe eine Menge Zeug gelesen, was Threads abgeblich nicht dürfen und das man sie am besten nicht verwenden soll.Ich will aber !!!

- wie kommuniziert man am besten mit Threads bzw. Threads untereinander...? Es geht um mehr als Signalisierung, es sollen auch Daten übergeben werden.

- welche Alternativen habe ich, um die geforderten Funktionalitäten ohne Threads zu realisieren...? Ich habe gelesen: Callbacks...?

Mir ist auch aufgefallen, das oft, wenn es um etwas kniffliges geht, einfach ein Stück Winapi Code präsentiert wird.Das ist sicher hier und da hilfreich, aber eigentlich wollte ich PureBasic sprechen und nicht WinApi.Sonst könnte ich ja gleich Visual-irgendwas nehmen.

Soll ich besser nen eigenen Thread ( oops..der war das böse Wort wieder...)für jedes dieser Themen im Forum öffnen, da dies ja doch recht umfangreich ist...?

Freue mich über jede Anregung bzw. Problemlösung...

Achso...die Struktur von meinem Projekt sieht so aus:

Main: ist eigentlich nur das GUI bzw. dessen Eventloop
Thread 1: beschafft Daten und speichert diese in Dateien sowie Variablen
Thread 2: testet etwas und speichert das Ergebnis in eine Variable
Thread 3: aktualisiert GUI Gadgets von Variablen, die die anderen beiden Threads mit Inhalten befüllen.

Thread 4 soll jetzt mal keine Rolle spielen, der wird normal nicht gestartet.


Grüße

TWELVE
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

> ist schon eine Weile her

welcome back
Wen es interessiert: ich hatte in der Event Loop zuviel zusätzlichen Code drin, der den Update einiger Gadgets erledigt hat. "Lustigerweise" bin ich darauf gekommen, weil man mir hier im Forum ( und auch anderswo) von der Verwendung von Threads abgeraten hatte. Also habe ich krampfhaft versucht, das Meiste im Main unterzubringen und Thread zu vermeiden.
manche Gadgets erzeugen beim updaten wieder ein event.
wenn du zu oft gadgets updatest, kann deine Event-Queue überlaufen.
als abhilfe kannst du die updates dann durchführen (in der hauptschleife) wenn kein anderes event aufgetreten ist.

Code: Alles auswählen

Event = WaitWindowEvent(20)

Select Event

; ... alle möglichen Events

  Case 0     ; kein Event
    ; Gadgets updaten
auch hier braucht man nicht unbedingt threads, man muss nur wissen, was man tut... ;)
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

Öhm ... ich nutze auch gut und gerne Threads ... weils teilweise
übersichtlicher ist ... z.B. beim Laden ein Fenster als Thread laufen zu
haben und das Hauptprogramm lädt dann munter die Daten. Oder anders
rum :mrgreen:

... genau das hab ich bei meinem letzten Programm (mal wieder nen
blödes Zwischenprojekt, ich lerns nie /:-> ) auch gemacht. Ich hab auch
keine Probleme ohne Debugger oder so ... lief alles super wie immer.
Dann geb ich das den Leuten, die das Programm eigentlich nutzen sollen
... und bekomm zurück, das Programm bricht direkt am Anfang
ab. :shock: ... Windows hat einen Fehler festgestellt blablabla ...

*freu* ... toll, ... naja ich war mit meinem Latein ja noch nicht am ende,
also hab ich das ganze mit "OnError"-Unterstützung kompiliert,
entsprechenden zusatzcode rein kopiert ... is ja nicht so als ob ich die Lib
das erste mal verwendet hab :lol: ... und wieder den Leuten gegeben.
Das Ergebnis: "WaitWindowEvent(50)" war der übeltäter :?

*noch mal freu* ... OK, Threadsafe gibs ja auch noch ... das wird ja wohl
dann laufen ... und tatsächlich, es läuft ... aber warum??? ... bei 2/4 läufts
ohne Threadsafe nicht ... inzwischen weis ich, das 2 davon AMD-
Prozessoren, 2 davon Intel-Prozessoren haben.

Welchen Prozessorhersteller nutzt du? :D
... eventuell hast du nämlich das selbe Problem^^
... und dann wäre ich auch für eine Lösung (Bug behebung? :mrgreen: )
sehr erfreut, weil ich nicht gerne "Threadsafe" verwende, da bin ich nach
wie vor sehr skeptisch was die Fehlerquellen angeht ^_^

Dieser Post entspricht wahren Ereignissen und ist nicht zum Anfachen
einer Diskusion über Intel vs. AMD gedacht!

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
TWELVE
Beiträge: 72
Registriert: 01.04.2007 18:33

Beitrag von TWELVE »

manche Gadgets erzeugen beim updaten wieder ein event.
wenn du zu oft gadgets updatest, kann deine Event-Queue überlaufen.
als abhilfe kannst du die updates dann durchführen (in der hauptschleife) wenn kein anderes event aufgetreten ist.
Gute Idee...werd ich mal probieren.Läuft aber auch wieder darauf hinaus, Threads zu elimieren.Anscheinend will da keiner richtig ran...:-))
auch hier braucht man nicht unbedingt threads, man muss nur wissen, was man tut...
Versuchen wir das nicht alle..? :-) Ich muß nur die Konventionen kennen, dann kann ich auch sicher Threads verwenden.

Welchen Prozessorhersteller nutzt du?
... eventuell hast du nämlich das selbe Problem^^
... und dann wäre ich auch für eine Lösung (Bug behebung? )
sehr erfreut, weil ich nicht gerne "Threadsafe" verwende, da bin ich nach
wie vor sehr skeptisch was die Fehlerquellen angeht ^_^
Ich habe zum Test bisher Intel Pentium M und Core2 Duo M verwendet ( ich muß meinen Code immer dabei haben, deshalb nur Notebook :-)) ).Hatte ich aber oben gschrieben..:D

Hast Du ein handfestes Konzept, die Threads/ den Main Code zu schützen oder vertraust Du darauf, das es schon laufen wird..?



Grüße

TWELVE
Emily
Beiträge: 96
Registriert: 25.01.2008 13:14

Beitrag von Emily »

Wenn die Abstürze mit Threadsafe nicht auftreten, dann hast du vermutlich ein Synchronisationsproblem. Nebenläufigkeit ist ein sehr heikles Ding, dass man nur nutzen sollte wenn man viel davon versteht und das auch geradezu schlafwandlerisch Anwenden kann.

Unter http://hyfisch.de/HyFISCH/Informieren/N ... igkeit.pdf
kannst du schon ein bisschen dazu lesen. Nicht alle Lösungsansätze lassen sich so ohne weiteres auf PureBasic anwenden und es würde mich auch wundern wenn du dazu viele PureBasic Beispiele findest.
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

Ich weis, was ich machen muss damit es laufen sollte :wink:
... ich beschäftige mich mit dem Problem aber auch schon ein paar Jahre.
Und wenn ein Fehler auftritt, weis ich in so ziemlich jedem Fall, wo er in
etwa sein müsste oder wie ich ihn raus bekomme. Deswegen hab ich
nicht so viele Probleme mit Threads, dennoch nutze ich sie auch wirklich
nur dann, wenn es mir wirklich für besser erscheint ... wie z.B. beim
laden wegen der Übersichtlichkeit. Es hat seinen Grund, warum alle von
der nutzung abraten, wenn man nicht 100% weis, was man tut, kann man
sein Programm unnötig instabil machen und darann verzweifeln. :wink:

Ich glaub, in der Zeit hab ich aber immer nur meinen Rechner zum testen
verwendet, und das ist nen AMD ... ich muss wohl mal demnächst
schauen, ob das Problem auch mit wenig Code auftritt und dann mal
schauen, was die wirklichen Profis wissen ...

Ich hab hoffnung, dass es wirklich ein Bug von PB ist ... aber es kann
auch sein, dass Intel-CPUs es schlicht und ergreifent anders hand haben
und deswegen Threadsafe dafür unverzichtbar ist. Dann würd mich aber
interessieren, wies vor PB4 gewesen ist ^_^ ... da gabs die Möglichkeit ja
noch nicht.

Aber ob genau das bei dir zutrifft kann ich nicht sagen. Was ich mit
meinem Post dir aber auch noch (indirekt) sagen wollte, wie du das
wirkliche Problem findest ... nutze die OnError-Library von PB und teste
deine Executable dann ohne Threadsafe ... lass dir in einem MSG-Fenster
anzeigen, in welcher Zeile der Fehler auftritt.

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
TWELVE
Beiträge: 72
Registriert: 01.04.2007 18:33

Beitrag von TWELVE »

Wenn die Abstürze mit Threadsafe nicht auftreten, dann hast du vermutlich ein Synchronisationsproblem. Nebenläufigkeit ist ein sehr heikles Ding, dass man nur nutzen sollte wenn man viel davon versteht und das auch geradezu schlafwandlerisch Anwenden kann.
Mmmmh...:D Hier gehts aber eigentlich um was anderes...nämlich um Programmabstürze durch Access Violation.Mit Deiner "Nebenläufigkeit" hat das nichts zu tun.Wenn da etwas nicht synchron ist, dann funktioniert mein Programm nicht so, wie es soll.Das tut es aber - bis es abstürzt.

Access Violation bedeutet, ich - ähm also mein Code :D - greift auf etwas zu, was es nicht darf.Wenn Du 2 verschiedene Programme startest, dürfen sich auch nicht gegenseitig im Speicher rumschreiben.Damit das nicht passiert, paßt die CPU ( die MMU oder wie immer die Unit jetzt heißt) darauf auf und springt in eine Exception, falls das passiert.Und ich möchte, das das aufhört..:D Dazu muß ich erst den Verursacher finden, erst dann kann ich den Code korrigieren...:D


Grüße

TWELVE
TWELVE
Beiträge: 72
Registriert: 01.04.2007 18:33

Beitrag von TWELVE »

Deswegen hab ich nicht so viele Probleme mit Threads, dennoch nutze ich sie auch wirklich nur dann, wenn es mir wirklich für besser erscheint ... wie z.B. beim laden wegen der Übersichtlichkeit.
Dito...:-) Ich habe keine massiven Probleme mit Threads.Ich habe eine Code Basis genommen, die habe ich vor ca. einem Jahr entworfen.Die lief stabil.Dann habe ich den Code ausgebaut, modifiziert und aufgeräumt.Natürlich immer Testrun.Alles lief...aber meist nur mit Debugger.Das Problem ist nach 2 Wochen einfach so aufgetreten, bei Ausführung als exe.

Grüße

TWELVE
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

TWELVE hat geschrieben:
Deswegen hab ich nicht so viele Probleme mit Threads, dennoch nutze ich sie auch wirklich nur dann, wenn es mir wirklich für besser erscheint ... wie z.B. beim laden wegen der Übersichtlichkeit.
Dito...:-)
Dann sollte es für dich kein Problem sein, den problematischen
Codeabschnitt selber zu finden :wink:
... weil genau das deine Zitierte-Aussage ist :D

Bei Threads tritt grundsätzlich etwas "aufeinmal" auf, zumindest in PB. :wink:

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Antworten