On program startup I create an array of structures. I wanted it global, but don't know at startup how many records I'll need so did it like this:
Code: Select all
Structure tFoo
String1.s
String2.s
EndStructure
Global Dim xInfo.tFoo(0) ; intially just one element
; ...
Redim xInfo(lMax) ; later in program, redim to the # of items I need and assign contents
; ...
xInfo(x)\String1="hello"
xInfo(x)\String2="world"
Later in the program I do some work, during which some new maps are created and used, etc. I want to pass it a single record from the array, so I've been doing it like this:
Code: Select all
DoSomeWork(@xInfo(n)) ; which I assume passes the address of the Nth record in array
; ...and in the procedure I have the parameter passing declared as:
Procedure DoSomeWork(*OneRecord.tFoo)
...
EndProcedure
THE QUESTION: Now, DoSomeWork can take some time, so I then tried having it run on a separate thread. I call it like this:
Code: Select all
lThreadHandle=CreateThread(@BackgroundWork(),n)
Procedure Backgroundwork(*Value)
Define n.l ;at this point should already be executing on new thread
n=*Value
DoSomeWork(@xInfo(n))
EndProcedure
Yes the new thread for DoSomeWork allocates a number of new objects in memory, like NewMaps and map elements. But in my mind nothing being allocated should ever be able to overwrite contents of the original array or its strings as all of that was allocated ahead of time.
DoSomeWork reads from the xInfo record it is handed, but doesn't write to it. Yet the contents get corrupted, only when threading used. If I drop the CreateThread and call DoSomeWork directly, no problems.
Finally, DoSomeWork() uses a global map during processing. I wanted each worker thread to have its own copy of the map, so used 'threaded' declare. But discovered:
Code: Select all
Threaded NewMap SomeMap() ; when declared like this, the xInfo corruption DOES occur.
Global NewMap SomeMap() ; when declared like this, corruption DOES NOT occur.
(Thanks in advance to anyone who read this far!)