Question

I have the following code, where I start a Thread using a ParameterizedThreadStart object as constructor argument:

static object obj = new object();

static void Main(string[] args)
{
    ParameterizedThreadStart start = (o) =>
    {
        ThreadTest(o);
    };

    var t = new Thread(() => start(obj));
    t.Name = "t";
    t.Start();

    Thread.Sleep(3000);
    obj = null;

    // Why the Thread (t) continue here??
    Console.ReadKey();
}


private static void ThreadTest(object o)
{
    while (o != null)
    {
        Console.WriteLine(Thread.CurrentThread.Name);
        Thread.Sleep(1000);
    }
}

After I set obj to null in the ThreadTest method the argument o is still a valid object, why?
How can I set the argument o to null using obj?

I would prefer not to use Thread.Abort

Was it helpful?

Solution

Because in C#, references are passed by value.

So, changing obj to refer to NULL in Main will not change the object to which o refers in ThreadTest.

Instead, you should keep both methods referring to the same object, and just change a property of the object to signal that the thread should exit.

OTHER TIPS

o is a local parameter in your ThreadTest method.
Assigning the obj field does not affect that parameter.

You can fix this by getting rid of all of the parameters and using the field directly. Once you do that, your code will still be broken, because the field is not volatile.

You're passing the value of a reference when calling the method. This means that any changes to the reference inside will not be seen outside and vice-versa. You'll probably want to synchronize directly at the global variable level:

static volatile object obj = new object();

static void Main(string[] args)
{
    ThreadStart start = () =>
    {
        ThreadTest();
    };

    var t = new Thread(() => start());
    t.Name = "t";
    t.Start();

    Thread.Sleep(3000);
    obj = null;

    // Why the Thread (t) continue here??
    Console.ReadKey();
}


private static void ThreadTest()
{
    while (obj != null)
    {
        Console.WriteLine(Thread.CurrentThread.Name);
        Thread.Sleep(1000);
    }
}

Note also the volatile on the object. This will ensure that changes by one thread will be visible to other threads reading the value.

Try using a Boolean to control the thread stop like so:

static volatile bool runThread = true;

static void Main(string[] args)
{
    var t = new Thread(ThreadTest);
    t.Start();

    Thread.Sleep(3000);
    runThread = false;

    Console.ReadKey();
}


private static void ThreadTest()
{
    while (runThread)
    {
        Console.WriteLine(Thread.CurrentThread.Name);
        Thread.Sleep(1000);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top