Thread Parameters Being Changed

Thread parameters being changed

You should be careful about accidentally modifying captured variables like i after starting the thread, because the i is shared. The i variable refers to the same memory location throughout the loop’s lifetime. The solution is to use a temporary variable like this:

for (int i = 0; i < _threadCount; i++)
{
var i1 = i;
Thread thread = new Thread(() => WorkerThread(i1));
thread.Start();
_threads.Add(thread);
}

Read more about Closures here : The Beauty of Closures from (Jon Skeet) and Lambda expressions and captured variables from (Joseph Albahari).

Change parameters value in a method during its execution in a thread

You could create a shared variable meant for communicating between two threads

class ArgumentObject
{
public bool isOk;
}

// later
thread1Argument = new ArgumentObject() { isOk = true };
TrdColCycl thread = new Thread (() => this.ColorsCycling (thread1Argument));
trdColCycl.Start();

// much later
thread1Argument.isOk = false;

Edit:

Alternatively, you could pass the bool as reference instead:

bool isOk = true;
TrdColCycl thread = new Thread (() => this.ColorsCycling (ref isOk));
trdColCycl.Start();

// later
isOk = false;

In both cases, you'll have to modify the signature of your method:

// original
void ColorsCycling(bool isOk)
// should be
void ColorsCycling(ArgumentObject argument) // for option 1
// or
void ColorsCycling(ref bool isOk) // for option 2

CreateThread parameter value changes unexpectedly

This fails simply because in your first example you are passing the pointer to the same memory location for all 4 threads. The fact that you incremented the value before passing the pointer is inconsequential, as the memory location stays the same.

In your second example you instead pass 4, mutually exclusive pointers to the 4 threads. Therefore, the threads all read independent values.

You could restructure your code slightly to help with maintainability and flexibility:

int threadData[NTHREADS]; /* in the future this could be an array of structs */
HANDLE threads[NTHREADS];
int tt;

for (tt = 0; tt < NTHREADS; ++tt)
{
threadData[tt] = tt + 1; /* placeholder for actual logic */
threads[tt] = CreateThread(
NULL, /* lpThreadAttributes */
0, /* dwStackSize */
my_thread_1, /* lpStartAddress */
&threadData[tt], /* lpParameter: each thread will receive its own data */
0, /* dwCreationFlags */
NULL /* lpThreadId */);
}

/* Since threadData and threads are local to the enclosing scope,
* we must wait for them to finish here to ensure we don't read
* data we no longer own
*/
WaitForMultipleObjects(NTHREADS, threads, TRUE, INFINITE);

Change a thread argument python?

Just make a new thread. I'd recommend having a function to create the threads like this:

def waitTrigThreadMaker(argForWaitTrig):
"""Makes a thread with the given arg and waits for it to finish"""
waitTrigThread = threading.Thread(target=tek.waitTrig ,args=[argForWaitTrig])
waitTrigThread.run()
waitTrigThread.join()

If you want other things to run while the thread executes then you can do something like this:

def waitTrigThreadMaker(argForWaitTrig):
"""Returns thread for the given arg"""
waitTrigThread = threading.Thread(target=tek.waitTrig ,args=[argForWaitTrig])
waitTrigThread.run()
return waitTrigThread

def waitTrigThreadJoiner(threadList):
"""Joins all threads"""
for myThread in threadList:
myThread.join()

This code would then be used like this:

threadList = list()
for myData in myDataList:
threadList.append(waitTrigThreadMaker(myData))
#whatever other code you want to run as the threads are working
waitTrigThreadJoiner(threadList)

Use the first block of code if you cannot run the threads concurrently and use the second block of code if you can run the threads concurrently.

Value of the variable passed as reference gets changed in threads

This is because pthread_join has the prototype void **. It expects a pointer to an object of type void *; it modifies this void * object. Now it so happens that you're running on a 64-bit arch, where data and value are both 32 bits, and laid out in memory sequentially. Modifying a void * object that is laid out in memory starting from the address of the int object value clobbers the int object data too, as these are both 32 bits - thus you will see that the data was overwritten. However, this is undefined behaviour so anything might happen.


Don't use casts as they will only serve to hide problems. Casting to a void * is especially dangerous as a void * can be converted to any other type implicitly, even to void **, even though usually it too would be incorrect. If you remove the cast, you most probably will get a warning or an error like

thrtest.c: In function ‘main’:
thrtest.c:16:31: error: passing argument 2 of ‘pthread_join’ from
incompatible pointer type [-Werror=incompatible-pointer-types]
pthread_join (thread, &value);

if compiling with warnings enabled.


If however you really want to do this, you must do it like this:

void *value;
pthread_join(thread, &value);
intptr_t value_as_int = (intptr_t)value;

Though it is not really portable either, as the conversion is implementation-defined.

The most portable way to return an integer is to return a pointer to a mallocated object:

int *return_value = malloc(sizeof (int));
*return_value = 42;
return return_value;

...

void *value;
pthread_join(thread, &value);
int actual = *(int *)value;
free(value);

Why is my variable not changing when modified in separate thread? c++/boost

You give the thread a reference to the chunk variable, which does no longer 'exist' after exiting the for loop.

So you may see the thread changing some value, but it really dereferences some stale chunk variable, uses the (unpredictable) content as a pointer, changes the memory location of what it thinks is the changed member.

You shouldn't give it a ref. The thread needs the actual pointer, not the variable holding the pointer.



Related Topics



Leave a reply



Submit