准备在另一个线程中使用的操作

时间:2012-05-11 19:16:04

标签: c# multithreading properties action

我想定义一个动作,用一个值(由工作线程计算)设置一个属性。应该在另一个线程上下文(UI线程)中调用该操作。

为了简化问题,它归结为一个问题:为什么这些代码不起作用,我需要做些什么才能使其按预期工作:

    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");
    }

为什么这会给我&#34; null&#34;而不是&#34;萨米&#34;?

3 个答案:

答案 0 :(得分:4)

类型Person是一个结构。这意味着当您将person作为参数传递时,会生成一个副本。因此,操作会更新副本,而不是person本身。如果您将Person更改为某个班级,您会看到您的示例有效。

有关结构和类之间区别的更多信息,请参阅what's the difference between struct and class in .Net?

答案 1 :(得分:1)

要证明@ ElianEbbing的回答:

   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;
   }

因为您将Person声明为结构,所以它是一个值类型 - 意味着创建了Person的副本。 Name设置为“Sami”的Person对象与用于写入名称的Person对象不同。

答案 2 :(得分:1)

您正在使用错误的线程和操作。通过创建一个线程(设置一个动作来设置人名),你实际上没有做任何特别的事情。

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

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

你想要的是这样的:

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