2

I want do define an action that sets a property with a value (calculated by a worker thread). That action should be called in another thread context (UI thread).

To simplify the problem - it boils down to the question: why does this code don't work and what do I have to do to make it work like intended:

    public struct Person
    {
        public string Name;
    }

    Person person;
    Action<Person> action;

    public void Update()
    {
        person = new Person();

        new Thread(() =>
        {
            action = new Action<Person>(c => c.Name = "Me");
        }).Start();

        Thread.Sleep(1000);
        action(person);

        Debug.WriteLine(person.Name ?? "null");
    }

Why is this giving me "null" instead of "Sami"?

IAbstract
  • 19,551
  • 15
  • 98
  • 146

3 Answers3

4

The type Person is a struct. This means that when you pass person as an argument, a copy is made. So the action updates a copy, a not person itself. If you change Person to a class, you will see that your example works.

For more information about the difference between structs and classes, see what's the difference between struct and class in .Net?

Community
  • 1
  • 1
Elian Ebbing
  • 18,779
  • 5
  • 48
  • 56
1

To prove @ElianEbbing's answer:

   class Program {
      Person person;
      Action<Person> action;
      static void Main(string[] args) {
         Program p = new Program();
         p.Update();

         Console.ReadLine();
      }
      public void Update() {
         person = new Person();

         new Thread(() => {
            action = new Action<Person>(c => c.Name = "Sami");
         }).Start();

         Thread.Sleep(1000);
         action(person);

         Console.WriteLine(person.Name ?? "null");
      }
   }

   public class Person {
      public string Name;
   }

Because you declare Person as a struct, it is a value type - meaning a copy of Person is made. The Person object that has Name set to "Sami" is not the same Person object you are using to write the name.

IAbstract
  • 19,551
  • 15
  • 98
  • 146
1

You are using threads and actions wrong. By creating a thread that (sets an action to set the person's name), you are effectively doing nothing special.

    new Thread(() =>
    {
        action = new Action<Person>(c => c.Name = "Me");
    }).Start();
    Thread.Sleep(1000);

is the same as

action = new Action<Person>(c => c.Name = "Me");
action(person);

What you wanted was something like this:

action = new Action<Person>(c => c.Name = "Me");
new Thread(action).Start();
Thread.Sleep(1000);
Oblivion2000
  • 616
  • 4
  • 9
  • I was thinking the same thing but I didn't consider making corrections there. Although you do point out the correct use of action and Thread, it won't solve the OP's issue because `Person` is a struct. ;) – IAbstract May 11 '12 at 21:06
  • Oh, I see. You are absolutely correct. Thanks at all posters, u guys really helped me out! – Samara Lindner May 12 '12 at 08:29
  • Thought about this again - in the example I'm doing nothing special, but the thread is thought of as a worker thread. It may calculate something apart from the ui thread which i can use in the code within the action. I think I still need another thread to prepare the action. – Samara Lindner May 12 '12 at 09:05