英文:
Can I be guaranteed that a variable value will be passed along to a new running Task?
问题
我是否可以假定以下代码将始终通过我的断言?我担心索引值。我不确定作用域值是否会传递到 Task.Run 的 lambda 表达式中。我认为它会像 attributesChunked 值一样作用域化。但我想要一些确认。
var tasks = new List<Task>();
var attributes = new string[4]{ "att1", "att2", "att3", "att4" };
var chunkIndex = -1;
foreach (var attributesChunked in attributes.Chunk(2))
{
var index = Interlocked.Increment(ref chunkIndex);
tasks.Add(Task.Run(() =>
{
if (index == 0)
Assert.Equal("attr1", attributesChunked.First());
if (index == 2)
Assert.Equal("attr3", attributesChunked.First());
}));
}
await Task.WhenAll(tasks);
英文:
Can I assume the following code will always pass my assertions? I'm a worried about the index value. I'm not sure if the scoped value will be passed along to the Task.Run lambda expression. I think it will be scoped just like the attributesChunked value seems to be. But I'd like some confirmation.
var tasks = new List<Task>();
var attributes = new string[4]{ "att1", "att2", "att3", "att4" };
var chunkIndex = -1;
foreach (var attributesChunked in attributes.Chunk(2))
{
var index = Interlocked.Increment(ref chunkIndex);
tasks.Add(Task.Run(() =>
{
if (index == 0)
Assert.Equal("attr1", attributesChunked.First());
if (index == 2)
Assert.Equal("attr3", attributesChunked.First());
}
}
await Task.WhenAll(tasks);
答案1
得分: 2
对于您创建的每个任务,您都引入了一个在该迭代中声明的索引变量的闭包。因此,是的,您的任务将使用正确的值,可以使用以下代码进行测试:
static async Task Main(string[] args)
{
var tasks = new List<Task>();
var attributes = new string[4] { "att1", "att2", "att3", "att4" };
var chunkIndex = -1;
foreach (var attributesChunked in attributes.Chunk(2))
{
var index = Interlocked.Increment(ref chunkIndex);
tasks.Add(Task.Run(async () =>
{
// 模拟一些工作...
await Task.Delay(50);
Console.WriteLine($"index: {index}");
}));
}
await Task.WhenAll(tasks);
}
结果:
index: 0
index: 1
请注意,输出的顺序完全取决于各个任务的调度,无法预测...
有用的参考链接:https://stackoverflow.com/questions/428617/what-are-closures-in-net
英文:
For each task you create, you are introducing a closure on the index variable declared in that iteration. So yes your Task will use the right value, as can be tested using following code:
static async Task Main(string[] args)
{
var tasks = new List<Task>();
var attributes = new string[4] { "att1", "att2", "att3", "att4" };
var chunkIndex = -1;
foreach (var attributesChunked in attributes.Chunk(2))
{
var index = Interlocked.Increment(ref chunkIndex);
tasks.Add(Task.Run(async () =>
{
//simulate some work...
await Task.Delay(50);
Console.WriteLine($"index: {index}");
}));
}
await Task.WhenAll(tasks);
}
The result:
> index: 0
> index: 1
Note that the sequence of the output is entirely dependent on the scheduling of the individual Tasks and cannot be predicted...
Useful reference: https://stackoverflow.com/questions/428617/what-are-closures-in-net
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论