2

我想定义一个设置属性值的操作(由工作线程计算)。应该在另一个线程上下文(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");
    }

为什么这给了我“null”而不是“Sami”?

4

3 回答 3

4

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

有关结构和类之间区别的更多信息,请参阅.Net 中结构和类之间的区别是什么?

于 2012-05-11T19:27:12.987 回答
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 对象不同。

于 2012-05-11T19:34:19.997 回答
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);
于 2012-05-11T19:35:25.120 回答