c# - 根据 "serial"心理模型而不是 "last value"将状态变量赋予任务 lambdas?

标签 c# lambda task-parallel-library

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

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

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

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

最佳答案

对于这样的闭包场景,我通常只使用一个临时变量:

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

关于c# - 根据 "serial"心理模型而不是 "last value"将状态变量赋予任务 lambdas?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13964410/

相关文章:

c# - 我如何将 linq 转换为 lambda

c# - 多线程奇点

.net - Task.FromCanceled 中的cancelToken 参数的用途是什么?

c# - 将 Action 结果绑定(bind)到 MVC5 中的按钮

c# - 正则表达式解析两个标记之间的字符串,没有捕获组并排除标记

c# - 使用 mongodb c# 从字符串数组中提取值(如果包含子字符串)

c++ - 什么时候初始化 lambda 捕获?

java - 将方法作为参数传递——这可能吗?

c# - 如何创建运行 STA 线程的任务 (TPL)?

c# - 关于域模型及其可见性的问题