1

This is in Unity / Mono, but any .Net ...

Imagine some code like this

using System.Threading;
using System.Runtime.InteropServices;

public class Example: MonoBehaviour {

    [DllImport("__Internal")] private static extern void long_function();
    [DllImport("__Internal")] private static extern void short_function();
    public Thread happyThread;
    public void Test() {

        happyThread = new Thread(LongTest);
        happyThread.Start();
    }
    private void LongTest() { long_function(); }
    private void ShortTest() { short_function(); }
}

We run Test and thus long_function from the C library is launched. It is launched on another thread. ("happyThread ")

Say it takes 60 seconds to run.

  1. At the end of that time, does happyThread cease to exist? Or is it still there in Example scope? Or can you retain it or something??

  2. Let's say we know long_function finished. I then want to call ShortTest and hence short_function. Can you do something like this ..

Earlier we did this

        happyThread = new Thread(LongTest);

Can we now "change" the "contents" of the thread to

        happyThread.newStuff( ShortTest());
        happyThread.StartAgain();

or is that stupid and meaningless?

  1. Would I simply start ShortTest again just on another new Thread?

  2. Say the library has a simple global variable int k ...

So TBC, the C file which is built to the static library looks like this at the top:

// file happyLibrary.c Fattie(TM) 2019
#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
int k = 7; // (NB you almost certainly want volatile here in real apps)
void long_function
{
    ...
  1. ... which long_function sets to be 42. In fact .... will short_function be able to also later access that value?? Or? Only if I use the same thread or something? Again, k is a global global.

  2. if you have to launch zillions of little tasks, if there perhaps a performance advantage in re-using happyThread, if you can reuse 'em??

(I fully appreciate that, simply, long_function would persist over there and offer callbacks to the main thread, with the short_function concept; but, uh, I'm wondering about what I ask about above. Can you sort of "re-use" a thread? Can you get "in to" it again?)

Fattie
  • 27,874
  • 70
  • 431
  • 719

1 Answers1

3
  1. At the end of that time, does happyThread cease to exist? Or it still there in Example scope? Or can you retain it or something??

When the function called on the thread (in this case LongTest) finishes the lifecycle of the thread will end. The thread still exists as long as you have a reference to it in happyThread (You can see for yourself! happyThread.ManagedThreadId will still return the ID of the thread, even after it has finished), but it cannot be restarted. You can check the state of the thread by calling happyThread.ThreadState (which, at this point, will return stopped).

Can we now "change" the "contents" of the thread to

happyThread.newStuff( ShortTest());
happyThread.StartAgain();

No, you can not. You cannot bind a new function to a thread that is already terminated, and if you try to call happyThread.Start() on it again it will throw a ThreadStateException Thread has already been started..

Would I simply start ShortTest again just on another new Thread?

Yes. You will have to start ShortTest on a new Thread(ShortTest) (or you can just add it to the end of LongTest() method. any new method started on a thread will run on that thread). You can however call the new thread on the old happyThread. so happyThread = new Thread(ShortTest()) will happily start up again! You can even start a new thread on happyThread before the first thread runs out. so

Thread happyThread = new Thread(LongTest());//say this runs for 1 minute
happyThread.Start();
happyThread = new Thread(ShortTest());//this will start without a problem
happyThread.Start();

Will also happily start. Note however that this shouldn't be done really. It will make you lose the reference to the thread running LongTest. (And despite calling LongTest first, ShortTest may actually start running first if that thread happens to fire off first... this really is far from ideal, but just wanted to show it is possible.)

will short_function to also later access that value?

Yes, let's assume int k is public and global, and just runs on the main thread. You can set its value from long_function to 42, and later read int k's value from short_function on a different thread if you want. Now take note that you have to be careful with setting/getting variables over multiple threads to prevent race conditions.

If however you define int k inside the method running on a seperate thread it will go out of scope when the thread dies, just as any variable does that is initialized inside a function, when the function runs out.

You can use the volatile keyword to indicate that a variable might be modified by multiple threads. Msdn docs

if you have to launch zillions of little tasks...

If you'll be starting/closing a lot of threads you'll probably want to use ThreadPools

Can you sort of "re-use" a thread? Can you get "in to" it again?

So it all comes down to no. Once a thread dies it cannot start up again, also see this SO post about that specific topic.

However what you can do as an alternative is keep a thread alive for the duration of an application if you know you'll be calling to it alot or even continiously (for example I use this for keeping a TCP connection in the background that needs to always be accessible). This can be done like this:

Void Start()
{
    Thread happyThread = new thread(() => KeepAlivethread(1000));//short, easy way to create a delegate so you can pass parameters to your thread aswell!
    happyThread.Start();
}

volatile bool keepThreadAlive = true;//volatile because it may be accessed from another thread

private void KeepAliveThread(int timeout)
{
    Debug.Log("Thread started with id: " + Thread.CurrentThread.ManagedThreadId); 
    while (keepThreadAlive)
    {
        //do something, maybe have an event that calls to ShortTest.
        Thread.Sleep(timeout);
    }
    Debug.Log("Thread terminating with id: " + Thread.CurrentThread.ManagedThreadId);
}

Now this thread will keep running in the background until you set keepThreadAlive = false, after which it terminates gracefully. (do this so you don't have to thread.Abort(), which is bad! (more on that in the previously linked SO post's answer)

Remy
  • 4,843
  • 5
  • 30
  • 60
  • That's weird, for some reason the answer posted twice... but only partially the second time... – Remy Jan 17 '19 at 20:25
  • sometimes happens on a bad internet connection ;) – derHugo Jan 18 '19 at 06:40
  • **hold it!** @remy_rm Let's go to where it says: *"When the thread dies poor k dies with it."* k is a global global (note, I edited the question and I show where k is declared in the C source) .... surely that is not correct, k is still there and set to 42 when that thread dies right??? – Fattie Jan 18 '19 at 11:41
  • (Yes, it should be `volatile` - I didn't mention that not to add another issue !) But surely *When the thread dies poor k dies with it.* is incorrect if it is a global?? :O :O – Fattie Jan 18 '19 at 12:00
  • @Fattie You are completely right! oversight on my part. If `k` is global it will indeed stay around, regardless of what threads deals with it. *"when the thread dies poor k dies with it"* Should have been *"If `int k` is initialized on a method on a thread, the variable dies with it when the thread runs out, as it is goes out of scope as it would with any method"* is what that should've said! edited my asnwer! – Remy Jan 18 '19 at 12:04
  • PHEW ! THANKS ! :) – Fattie Jan 18 '19 at 12:09
  • bountyized this great answer! – Fattie Jan 24 '19 at 14:43