Seite 1 von 2

Thread mit String Parameter

Verfasst: 11.08.2008 08:27
von Marie23
Hallo, ist es möglich einen Thread mit String Parameter zu realisieren?

z.b.:

CreateThread(@MyThread(),MyStr.s)

funktioniert bei mir nicht


danke

Verfasst: 11.08.2008 09:23
von dige
Du kannst einen Zeiger auf einen String übergeben und den Text mit
PeekS() auslesen:

Code: Alles auswählen

Procedure ThreadExample ( *Pointer )
  Debug PeekS(*Pointer)
EndProcedure

Strings.s = "Marie23"
CreateThread(@ThreadExample(), @Strings )
Delay(5000)
End

Verfasst: 11.08.2008 10:34
von ts-soft
Es muß aber auch sichergestellt werden, das der String sich ncht ändert,
weil sonst wird der Zeiger auch ungültig.

Auf jedenfall ist das der sicherste Weg zum Crash, man übergibt keine
Strings (pointer zum string) an nem Thread!

Verfasst: 11.08.2008 11:33
von AND51
> man übergibt keine Strings (pointer zum string) an nem Thread
Darf man denn wenigstens einem allokierten Speicherbereich übergeben?

Code: Alles auswählen

*p=AllocateMemory(1024)
PokeS(*p, "Hallo Welt")
CreateThread(@myProc(), *p)
Die weitere Verwaltung des Speicherbeichs könnte man den Thread zumuten, d. h. der Thread gibt den Speicher ggf. wieder frei, sodass der Hauptthread nichts mehr damit zu tun hat.

Das wäre doch möglich, oder?

Verfasst: 11.08.2008 11:41
von Andreas_S
Kopieren wäre besser, da du normalerweise den Speicher auf den der Parameter zeigt nicht werändern sollst...

Verfasst: 11.08.2008 12:18
von Thorium
Andreas_S hat geschrieben:Kopieren wäre besser, da du normalerweise den Speicher auf den der Parameter zeigt nicht werändern sollst...
Wieso denn das?
Mit dem Speicher kann man machen was man will, bzw. mit dem Parameter. Das muss ja auch nicht zwingend ein Pointer sein.

So wie dige es macht, gibt es keine Probleme, wenn der String nicht mehr vom threaderstellenden Thread manipuliert wird.

Edit:
Man kann auch eine Structure übergeben, ist zwar etwas aufwendiger zu schreiben, sollte aber die schnellste und sicherste Möglichkeit sein.

Code: Alles auswählen

EnableExplicit

Structure StringStruct
  String.s
EndStructure


Procedure MyThread(*String.StringStruct)

  MessageRequester("",*String\String)

  End

EndProcedure

Define.StringStruct String

String\String = "Test"

CreateThread(@MyThread(),String)

Repeat
  Delay(100)
ForEver

Verfasst: 11.08.2008 17:06
von edel
Thorium hat geschrieben: So wie dige es macht, gibt es keine Probleme, wenn der String nicht mehr vom threaderstellenden Thread manipuliert wird.
Nur ist das manchmal gar nicht ersichtlich was mit dem Speicher passiert.
Rufst du z.b. aus einer Procedure einen Thread auf und uebergibst einen
lokalen String, kann es ja unter Umstaenden sein, das die aufrufende
Funktion schon beendet wurde (und somit auch der Speicher des Strings
freigegeben) und es im Thread dann irgendwann kracht.

Code: Alles auswählen

Procedure a(*string)
	
	;Delay(1000)
	
	Debug PeekS(*string)
	
EndProcedure

Procedure b()
	
	Protected s.s = "teststring"
	
	CreateThread(@a(),@s)
	
EndProcedure

b()
Delay(10000)

Eine Kopie ist in diesem Fall erforderlich.

Verfasst: 11.08.2008 17:52
von Kaeru Gaman
kann ich daraus den Schluß ziehen, dass es am sichersten wäre,
Strings, die von Threads I/O benutzt werden sollen, global anzulegen?

Verfasst: 11.08.2008 17:55
von edel
"Sicherer" ist es bestimmt, vertrauen wuerde ich darauf aber nicht,
da wir nicht wirklich wissen wie PB unter der Haube laeuft.

Verfasst: 11.08.2008 18:22
von helpy
Wenn der Pointer auf einen String übergeben wird (mit welcher Methode auch immer), muss in jedem Fall vom Programmierer sicher gestellt werden, dass der String nicht verändert wird, solange dieser nicht endgültig vom Thread (oder von was auch immer ;-)) verarbeitet worden ist.

Ich habe da vor kurzem etwas ähnliches, wie den folgenden Code verwendet:

Code: Alles auswählen

Procedure NewTmpString(s.s)
	Protected *s.String = AllocateMemory(StringByteLength(s)+SizeOf(Character))
	If *s
		PokeS(*s,s)
	EndIf
	ProcedureReturn *s
EndProcedure

Procedure.s GetTmpString(*s.String)
	Protected s.s
	If *s
		s = PeekS(*s)
		FreeMemory(*s)
	EndIf
	ProcedureReturn s
EndProcedure
Das ist nur eine Möglichkeit!

cu, guido