3

我理解闭包关闭引用而不是封闭变量的值。那不是我的问题。我想知道如何(向编译器)表达“给这个任务这个值,就像它在创建时看到的那样,而不是在执行时看到的”。

换句话说,我怎样才能得到

static void Main(string[] args)
{
    var userName = "Alice";
    var task = new Task(() =>
    {
        Console.WriteLine("User is: " + userName);
    });

    // continues work ...
    userName = "Zoltan";
    task.Start();
    Console.ReadLine();
}

打印

User is: Alice

而不是它现在所做的,即

User is: Zoltan

我试图避免

Task.Factory.StartNew((copy) =>
{
     Console.WriteLine("User is: " + (string)copy);
}, userName); 

这迫使我将每个状态对象(例如 userName)重新转换为实际 lambda 中的相应类型,因为StartNew方法接口将其定义为类型object而不是通用接口(例如:)<T>。上面的演示示例使用字符串和一个 writeline 似乎没问题 - 但对于一个大型对象的实际情况并在整个屏幕代码中重新转换它有点浪费(并且容易出错)。

4

1 回答 1

3

我通常只是简单地使用一个临时变量来处理这样的关闭场景:

var userName = "Alice";
var taskUserName = userName;
var task = new Task(() =>
{
    Console.WriteLine("User is: " + taskUserName);
});

编辑:

另一种完成相同事情但读起来略有不同的方法是将任务创建重构为一个方法:

static void Main(string[] args)
{
   var userName = "Alice";
   var task = CreateUserTask(userName);
   // ...
}

static Task CreateUserTask(string taskUserName)
{
    return new Task(() =>
    {
        Console.WriteLine("User is: " + taskUserName);
    });
}
于 2012-12-20T14:13:12.953 回答