Seite 2 von 6

Verfasst: 12.11.2008 21:56
von Thorium
Achso, dachte der Democode läuft.
Crasht der bei dir immer dort? Ich hab den Democode jetzt ein paar mal bei mir unter 4.30 B4 laufen lassen und keinen Crash gehabt, auch ohne Mutex kein Crash. Threadsave natürlich deaktiviert. Vieleicht muss ichs noch ein paar mal öffter laufen lassen.

Edit: 1 Millionen Druchläufe und kein Crash :freak: Das Teil will einfach nicht crashen bei mir.

Verfasst: 12.11.2008 22:24
von Fluid Byte
Wie gesagt, Threads sind schon 'ne feine Sache ... :mrgreen:

Also du sollst es auf keinen Fall immer komplett durchlaufen lassen. Immer nur ein paar Sekunden, dann killen und nochmal ausführen. Ich hab' auch PB4.30b4 und es crashed fast bei jedem zweiten Durchlauf. :|

Verfasst: 12.11.2008 22:25
von HeX0R
So scheint es zu gehn:

Code: Alles auswählen

EnableExplicit

Global Mutex = CreateMutex()

Declare DataAccessProc(lParam)
Define Highscore

Define i, DataAccessing, ThreadID, TempDir$

Procedure.s MyFunction(Wert1,Wert2)
	; anderer Kram
EndProcedure

For i=1 To 9999
	DataAccessing = 1
	If IsThread(ThreadID) = 0
		ThreadID = CreateThread(@DataAccessProc(),@DataAccessing)
		LockMutex(Mutex)
		TempDir$ = GetTemporaryDirectory()
		UnlockMutex(Mutex)
	EndIf
Next

Procedure DataAccessProc(lParam)
	LockMutex(Mutex)

	Protected HighScore$ = MyFunction(1,20)

	PokeL(lParam,0)

	UnlockMutex(Mutex)
EndProcedure
Offensichtlich musst du dann alle deine Stringoperationen, egal ob im Thread oder ausserhalb, via Mutex abkapseln.
Wohl wegen dem hier
Thorium hat geschrieben: Dann greift PB intern auf irgendwas mehrfach gleichzeitig zu
Nur, ob das dann im Endeffekt performanter als die Threadsavevariante ist, ist fraglich.

Verfasst: 12.11.2008 22:47
von Fluid Byte
Es geht auch ohne Mutex. Einfach ein "Delay(10)" nach "CreateThread()" packen ... :freak:

Mit Verlaub, ich bin jetzt etwas verwirrt ... :|

Verfasst: 13.11.2008 00:14
von Fluid Byte
Tja, was soll ich sagen? Ich hab' in mein Programm ein "Delay(10)" nach CreateThread()" eingefügt und nun kannste ich machen was du willst, es schmiert nicht mehr ab. Und das ohne Threadsafe!

Bug? :?

Verfasst: 13.11.2008 08:20
von Thorium
Irgendwo wurde mal geschrieben das PB einen Stringpool verwendet. Hängt warscheinlich damit zusammen. Das Delay sorgt ganz einfach dafür, das die String-Operation "Protected HighScore$ = MyFunction(1,20)" schon abgearbeitet werden kann, bevor die andere Stringoperation durchgeführt wird "TempDir$ = GetTemporaryDirectory()". Von daher schon logisch nachvollziehbar.

Ich würde jetzt mal sagen man kommt garnicht an Threadsave vorbei, wenn man innerhalb der Threads Strings verwenden möchte.

Verfasst: 13.11.2008 10:15
von helpy
Ein Anmerkung zu folgendem Code-Ausschnitt:

Code: Alles auswählen

For i=1 To 9999
   ...
   If IsThread(ThreadID) = 0
      ThreadID = CreateThread(@DataAccessProc(),@DataAccessing)
      ...
   EndIf
Next
Ich finde diese Schleife etwas seltsam. Wenn ich das richtig interpretiere, dann kann hier ja doch nur EIN Thread laufen:
  1. i=1 ==> ThreadID ist 0, da dieser vorher noch nicht gesetzt wurde. D.h. IsThread(ThreadID) gibt ebenfalls 0 zurück und in der Folge wird ein Thread erzeugt und die zugehörige ID in ThreadID gespeichert.
  2. i=2 ==> ThreadID enthält jetzt die ID des vorher erzeugten Threads! Ein neuer Thread wird nur dann erzeugt, wenn der zuvor erzeugte Thread beendet wurde, also wenn IsThread(ThreadID) 0 zurück gibt!
  3. i=3 ==> ...
Wozu also überhaupt einen Thread verwenden, wenn doch nur immer einer läuft!

Hier ein TEST-Code zur Cerdeutlichung:

Code: Alles auswählen

Procedure tTEST(loop)
	Debug "THREAD started in Loop " + Str(loop)
	Delay(1000)
	Debug "THREAD (" + Str(loop) + ") finished"
EndProcedure

For i=1 To 9999
	If Not IsThread(ThreadID)
		ThreadID = CreateThread(@tTEST(), i)
	EndIf
Next i

Debug "For/Next finished"

Delay(10000)

Debug "Program finished"
Ausgabe im Debug-Fenster:

Code: Alles auswählen

THREAD started in Loop 1
For/Next finished
THREAD (1) finished
Program finished

Verfasst: 13.11.2008 21:49
von HeX0R
Es ging doch lediglich darum irgendeinen Codemurks zu präsentieren, der den Fehler aufzeigt.

Verfasst: 13.11.2008 21:54
von ts-soft
> Wozu also überhaupt einen Thread verwenden, wenn doch nur immer einer läuft!
Hab jetzt nicht alles gelesen, aber das macht schon Sinn, wenn der Thread
länger benötigt, damit das Haupprogramm weiter geht.

Bei meinen bisherigen Tests mit Threads sind meine Programme meist langsamer geworden :lol:

Verfasst: 13.11.2008 22:25
von PMV
Ihr solltet auch klären, wer einen Intel und wer einen AMD-Prozessor hat.
Nicht der Flames wegen :lol: ... sondern weil Code ohne Threadsafe
wunderbar auf einem AMD laufen kann, obwohl der Intel-Prozessor streikt.
Muss nicht immer so sein, mir ist's bis jetzt nur ein mal passiert ... und ich
weis bis heute nicht worann es lag /:-> ... war aber glaub GUI-Zeug.

... ansonnsten folgendes:
Wie es aussieht brauchst du ja nur einen Thread, der alles lädt. Hier muss
also eigentlich nichts wirklich gesichert werden, du brauchst lediglich eine
Integer-Variable, die den Status des Threads anzeigen kann. Mit IsThread()
kannst du außerdem prüfen, ob der Thread noch wirklich läuft. Egal welche
Methode du wählst, so lange der Ladenthread läuft greifst einfach nicht
auf die Daten zu ... so kann auch nichts abschmieren.

Das Problem ist nur, das wir nicht wissen, wie die internen Funktionen
von PB arbeiten und ob diese eventuell Threadsafe benötigen. /:->

MFG PMV