我想定义一个动作,用一个值(由工作线程计算)设置一个属性。应该在另一个线程上下文(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;?
答案 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);