Seite 1 von 2

MessageRequester() nicht "threadsicher"/threadgeei

Verfasst: 06.05.2006 19:13
von Toshy
Hallo.

Also durch einen anderen Beitrag wollte ich was testen und dabei ist mir ein Problem mit MessageRequester() aufgefallen. In der Hilfe steht geschrieben
Öffnet einen ('blocking') Requester zum Anzeigen einiger Informationen. Die Programmausfhrung wird vollstndig angehalten, bis der Benutzer den Requester schliet.
Diese Aussage ist etwas unverständlich bzw. falsch wie ich vermute. Was ist mit "Programmausführung" gemeint!? Ich würde davon ausgehen, das der Prozess angehalten wird, aber das ist nicht korrekt, denn andere Threads laufen korrekt weiter. Sie sind also an sich weiterhin unabhängig. Aber sobald in unterschiedlichen Threads bzw. dem Hauptcode/-process ein Messagerequester aufgerufen wird blockiert dieser sehr wohl die komplette Ausführung, aber nur in den Threads, in den der MessageRequester() gerade ausgeführt wird. Das verhalten ist wie ich finde etwas eigenartig oder ist das beabsichtigt?

Bei der Beschreibung des MessageRequester() würde ich entweder davon ausgehen, das nur jeweils der Thread gestoppt wird, oder halt wirklich alle Thread ohne Ausnahme. Dem jetzigen Verhalten kann ich zwar auch einiges Gutes abgewinnen, aber es irritiert doch etwas und sollte doch mal klargestellt werden :-)

Gruß
Toshy

Verfasst: 09.05.2006 09:18
von real
Also ich finde es logisch. MessageRequester() erwartet einen Benutzerinput (durch Drücken eines Buttons) - also wird der Thread bzw. der Programmteil, in dem MessageRequester() aufgerufen wurde, bis zum erwarteten Benutzerinput gesperrt.

Verfasst: 09.05.2006 23:47
von Toshy
Diese Art ist unlogisch.

Es ist ja NICHT so, daß nur dieser Thread "angehalten" wird, sondern ALLE Thread die gerade den Messagerequester nutzen, alle anderen Threads laufen weiter. Ruft also Thread1 den MR auf, laufen alle anderen Threads noch weiter, solange bis bei denen auch "zufällig" ein MR ausgeführt wird. Aber nur der MR der nun zuletzt (oder war es der zuerst,hmm) aufgerufen wird ist nun anklickbar. Es werden also mehrere MR angezeigt, aber sind nicht anklickbar, nur einer.
Der MR stoppt also weder einen Process, noch eine Thread ansich, sondern läßt sich einfach nur nicht mehrfach parallel aufrufen (ohne beinflußt zu sein). Das verhalten ist schon eigenartig.

Und es hängt doch nicht vom Input an sich ab. Andere Inputabfragen sind doch auch Threadunabhängig, z.B. MessageBox_() läßt sich parallel problemlos nutzen.

Es kann ja sein, das der MR diese Art beabsichtig (warum auch immer), aber bisher sieht es eher danach aus, das er nicht korrekt threadkompatibel ist.

Das sollte unbedingt geklärt werden. Entweder muß das "fehlerhafte Verhalten" ausgebessert werden oder das "korrekte Verhalten" in der Hilfedatei genau beschrieben werden. Je nachdem was nun korrekt ist, muß man schließlich unterschiedlich programmieren.

Verfasst: 10.05.2006 01:06
von Kaeru Gaman
wenn mehrere threads in derselben prozessstruktur gleichzeitig einen message-requester aufrufen, hast du imho schon mal was falsch gemacht.

wenn verschiedene prozessestrukturen nen requester aufrufen, sind die optional zu beantworten.
die natur des msg-requesters ist darauf ausgelegt, den aufrufenden prozess einzufrieren, bis die msg. beantwortet ist.

ich kann mir grad nix ausdenken, wo von mehreren threads derselben prozesstruktur gleichzeitig mehrere msg-requester kommen sollten. was soll denn das sein?

PS:
punkto "fehlerhaftes verhalten ausbessern":
frag billie, der requester ist sein baby, PB ruft das dingen nur auf...

Verfasst: 10.05.2006 01:21
von ts-soft
Toshy hat geschrieben: Und es hängt doch nicht vom Input an sich ab. Andere Inputabfragen sind doch auch Threadunabhängig, z.B. MessageBox_() läßt sich parallel problemlos nutzen.
Schließe mich Kaeru an, möchte aber zu obigen noch folgendes sagen:
Beim Aufruf der API übergibste wahrscheinlich kein Handle als ersten
Parameter, sondern 0. PBs MessageRequester übergibt aber, wenn
vorhanden, das korrekte Handle, deshalb ein unterschiedliches verhalten.

Der MessageRequester verhält sich also korrekt, Deine Vorgehensweise mit
der API-Function ist nicht korrekt!

Verfasst: 10.05.2006 12:46
von real
Es gibt es tatsächlich einen Bug: Das oben beschriebene Verfahren mit MessageRequester funktioniert nur sporadisch. Ich habe, um Toshy's Info zum MessageBox_() selbst nachzuvollziehen, ein kleines Testprogramm gebastelt. Mit MessageBox_(0,...) alles nachvollziehbar. Wenn ich das Problem mit dem MessageRequester allerdings nachvollziehen will, blockiert er einmal den einen MessageRequester und einmal nicht... OHNE Codemodifikation. (Und natürlich hab ich es auch mal threadsicher kompiliert :wink:)

Hier der Code:

Code: Alles auswählen

Procedure Message(message.s)
  MessageRequester("Message",message)
EndProcedure

OpenWindow(0,0,0,200,200,"Test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CreateThread(@Message(),"Thread1")
CreateThread(@Message(),"Thread2")

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Das ganze sieht ungefähr so aus:
Bild

Wenn er schon das Handle des Windows mitgeben soll, dann wenigstens immer. Wenn er es manchmal tut und manchmal nicht ist das Mist. Ein wenig sollte schon Verlaß auf das sein, was PB da aus meinem Code macht (mal abgesehen davon, ob mein Code Sinn macht).[/b]

Verfasst: 10.05.2006 23:13
von ts-soft
Diese Art der MsgBox Verwendung ist einfach falsch. MsgBox sind dafür
ausgelegt, das Programm anzuhalten, bis geantwortet wurde. Für sowas muß
man eigene Fenster basteln, wenn man sowas unsinniges braucht. Fertig gibts
sowas nicht.

Wenn Du einen MessageRequester falsch verwendest, ist es egal ob es
immer gleich oder unterschiedlich reagiert. Ist IMHO kein Bug!!! Der Bug sitzt
eher vorm PC

Verfasst: 11.05.2006 03:01
von Toshy
@real
bei mir tritt der Fehler im Grunde immer auf, aber halt manchmal lassen sich beide MR bewegen und drücken. OHNE CODEANDERUNG wie du so schön schreibst, war aber erst 2 oder 3 mal der Fall. Hangt wohl vom Timing ab.
Und auch wenn es das Programm stoppen sollte, dann müßte doch der zuerst aufgerufene MR auch als erstes wieder "beendet" werden. Aber es kann immer nur der zu letzt aufgerufene bestätigt werden und da kann es schon mal passieren (je nach Programm) das bevor man klicken kann, ständig neue positioniert werden. Schön das du dieses Verhalten auch nachvollziehen konntest. Na ja, besser wäre es, wenn es nicht so wäre ;-)

@Kaeru Gaman

Das ist doch Quatsch. Funktionen sind dazu da aufgerufen zu werden, wo auch immer. Das hangt nun mal von dem ab was der Programmierer will. Und wenn man unabhängige Threads erstellt die verschiedene Programmteile abarbeiten, so kann es doch ganz logischer WEise dazu kommen, das man durch diese Threads auch eine Bildschirmausgabe bzw. Eingabe durchführen lassen will. Und dazu sind doch die Messagerequester da. Siehe auch meinen TExt zu ts-soft. Außerdem ist dies doch nur ein gekürztes Beispiel gewesen. Das tritt auch auf, wenn man den Messagerequester in unterschiedlichen Proceduren nutzt.

@ts-soft
Deine Aussage, das die Verwendung falsch ist, ist falsch. Mehr auch nicht. Die einzige Aussage die du nutzen könntest ist "Ich sehe für mich keine sinnvolle Verwendung...". Und wie kommst du darauf das es egal ist, das er unterschiedlich reagiert. Du bist wohl zu sehr an Microsoft gewöhnt ;-)
Verwenden kann man das an unterschiedlichsten stellen, die bei mir am meißten vorhandene Variante ich sind die eigenen Errorsubroutinen. Allociere ich z.B. einen SPeicherbereich, so geschieht das über eine Subroutine, tritt hier ein fehler auf, so kommt eine Requester. Diese Allocierungsroutine, wie auch die Errorroutine sind natürlich für alle Threads da. Bei anderen Fehler natürlich auch. Will man nun den Fehler rausfinden, kann ich nicht jeden Thread einzeln ausschließen, da alle Requester geblockt werden. Ich muß zwangsweise den mir angebotenen zuerst "freigeben".

@all
Alleine die Hilfe ist schon schwammig und das ist ja das Problem. Entweder die Hilfe ist nicht korrekt oder der MessageRequester buggy.
MessageRequester soll die Programmausführung anhalten. DAS MACHT ER NICHT. wird der MessageRequester aufgerufen, läuft das Programm normal weiter. ALLE anderen Thread werden nicht beeinflußt. den Process zu stoppen bzw. das Programm, dazu kann es also nicht dienen. Dient es dazu den Thread zu stoppen, dann stimmt das, aber dann dürfte der MR nicht die Threads gegenseitig blocken die den MR nutzen, aber nicht die anderen. Und dann macht er das auch noch nach Lust und Laune.Real hat das ja auch festgestellt. Zwar block er "fast immer", manchmal aber nicht. Die Hilfe erklärt das Verhalten nicht annähernd.

Also damit es klar ist, ich bin nicht davon überzeugt, das der Messagerequester buggy ist. Vielleicht muß er sich auch so verhalten. Vielleicht ist das das selbe Verhalten wie "die normale Messagebox", ich kannte bisher das interne Verhalten noch zu wenig (teste gerade), aber dann ist in der Hilfe die Erklärung nicht korrekt bzw. sehr schwammig. Eines von Beiden stimmt nicht: Die Erklärung in der Hilfe oder das Verhalten des MR.

Aber die MR verhält sich anders als die MB (mit WindowsID, vorausgesetzt ich da da keinen Fehler gemacht). Die MB block sich nicht gegenseitig.

Code: Alles auswählen

Global mh.l
Procedure repeat_(message.s) 
   Repeat
      Delay(1000)
      Debug "1"
   ForEver
   
EndProcedure 
Procedure Message(message.s) 
   MessageRequester("Message",message) 
EndProcedure 
Procedure Messagebx(message.s) 
   t.s = "ZickeZacke"
   MessageBox_(WindowID(mh) , @message, @t, 0) 
EndProcedure 
   
mh = OpenWindow(#PB_Any,0,0,200,200,"Test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) 
Debug WindowID(mh) 
CreateThread(@repeat_(),"") 
Delay(4000)
If 1 ;0
   CreateThread(@Messagebx(),"Thread3 MB") 
   CreateThread(@Messagebx(),"Thread4 MB") 
   CreateThread(@Messagebx(),"Thread5 MB") 
   CreateThread(@Messagebx(),"Thread6 MB") 
Else
   CreateThread(@Message(),"Thread1 MR") 
   CreateThread(@Message(),"Thread2 MR") 
   CreateThread(@Message(),"Thread3 MR") 
EndIf

Test ruhig mal. Die MB block nicht, der MR schon. ABER egal ob ich nun die MB vielleicht falsch erstellt habe (falsches handle), die MR macht nicht, was in der Hilfe steht. Das PRogramm läuft weiter, nur die "MR-Threads" blocken sich (fast immer) gegenseitig.

Also aus meiner Sicht stimmt da auf jeden Fall was nicht. Ob es die Erklärung in der Hilfe ist, kann uns nur das PB-Team sagen.

Verfasst: 11.05.2006 04:54
von ts-soft
Threads sind für Aufgaben im Hintergrund, die keinerlei Benutzerangaben
mehr erwarten. Alles andere ist schlechter und wie man sieht nicht
funktionierender Code. Benutzereingaben werden nur von der Mainloop
entgegen genommen. Bei Fehlern hält ein Thread an und meldet dieses der
Mainloop, die darauf reagiert.

Statt jetzt PB einen Bug unterzuschieben, lieber den Code so modifizieren,
das er Sicher läuft.

MessageRequester in einem Thread, noch nie gesehen :mrgreen:

Verfasst: 11.05.2006 08:15
von real
@ts-soft:
naja - weil du es nicht nutzt heißt das nicht, dass es dafür keine anwendungsmöglichkeiten gibt. wenn es mit der winapi (MessageBox()) allerdings funktioniert, sollte es auch unter pb so sauber funktionieren.