Strings in Threads ohne "Threadsafe"

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag 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.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag 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. :|
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Beitrag 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.
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Es geht auch ohne Mutex. Einfach ein "Delay(10)" nach "CreateThread()" packen ... :freak:

Mit Verlaub, ich bin jetzt etwas verwirrt ... :|
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag 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? :?
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag 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.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
helpy
Beiträge: 636
Registriert: 29.08.2004 13:29

Beitrag 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
Windows 10
PB Last Final / (Sometimes testing Beta versions)
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Beitrag von HeX0R »

Es ging doch lediglich darum irgendeinen Codemurks zu präsentieren, der den Fehler aufzeigt.
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 »

> 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:
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
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag 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
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Antworten