难道tasks.ToList()创建一个包含新复制的任务列表或列表是指在相同的任务? [英] Does tasks.ToList() create a list containing newly copied tasks or the list refers to the same tasks?

查看:124
本文介绍了难道tasks.ToList()创建一个包含新复制的任务列表或列表是指在相同的任务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有任务的阵列(称为'任务'),然后将其说转换到一个列表(称为临时):

 变种临时= tasks.ToList();
 

会发生什么事给那些正在运行的任务到数组元素呢?我们有两套任务单独运行(一个在'任务',另一个在'温度')?或者它们指向同一个任务?

下面code(从书考试参考70-483拍摄)是有关我在说什么(最后三个行):

 任务< INT> []任务=新的任务和LT; INT> [3];

任务[0] = Task.Run(()=> {Thread.sleep代码(2000);返回1;});
任务[1] = Task.Run(()=> {Thread.sleep代码(1000);返回2;});
任务[2] = Task.Run(()=> {Thread.sleep代码(3000);返回3;});

而(tasks.Length大于0){
    INT I = Task.WaitAny(任务);
    任务< INT> completedTask =任务[I]

    Console.WriteLine(completedTask.Result);

    变种临时= tasks.ToList();
    temp.RemoveAt(ⅰ);
    任务= temp.ToArray();
}
 

更新:我知道最后三行的目的,但不知道为什么它的工作

解决方案
  

会发生什么事[当我们调用了ToList的任务序列]我们有两套任务分别运行?或者它们指向同一个任务?

这其实是一个很好的问题,这取决于在其上调用了ToList 源序列。如果温度正在运行的任务(如你的情况),那么集合了ToList 简单地创建他们引用的副本,这意味着你的新名单将指向同一组任务。

但是,如果温度构成了还没有被实例化(由于延迟执行)的任务的顺序,那么你会得到一个的在每次调用了ToList 时设置任务。下面是一个简单的例子(使用的ToArray ,它具有相同的效果了ToList ):

 诠释计数= 0;

变种任务= Enumerable.Range(0,10)。选择(_ =>
    Task.Run(()=> Interlocked.Increment(引用计数)));

//任务= tasks.ToArray(); //推迟与积极执行

Task.WaitAll(tasks.ToArray());
Task.WaitAll(tasks.ToArray());

Console.WriteLine(计数);
 

如果你运行上面的code,最终的结果将是 20 ,这意味着两批任务中运行(每个的ToArray 调用)。但是,如果取消注释,使急于执行行,最后的结果将成为 10 ,表明后续的ToArray 调用只复制引用,而不是产生新的任务。

Assume we have an array of tasks (called 'tasks') and then convert it to a list (called 'temp') by saying:

var temp = tasks.ToList();

What happens to those running tasks to which the array elements point? Do we have two sets of tasks running separately (one in the 'tasks' and the other in 'temp')? Or they point to the same tasks?

The following code (taken from the book Exam Ref 70-483 ) is relevant to what I'm saying (the last three lines):

Task<int>[] tasks = new Task<int>[3];

tasks[0] = Task.Run(() => { Thread.Sleep(2000); return 1; });
tasks[1] = Task.Run(() => { Thread.Sleep(1000); return 2; });
tasks[2] = Task.Run(() => { Thread.Sleep(3000); return 3; });

while (tasks.Length > 0) {
    int i = Task.WaitAny(tasks);
    Task<int> completedTask = tasks[i];

    Console.WriteLine(completedTask.Result);

    var temp = tasks.ToList();
    temp.RemoveAt(i);
    tasks = temp.ToArray();
}

UPDATE: I know the purpose of the last three lines but do not know why it work.

解决方案

What happens [when we call ToList on a sequence of tasks]? Do we have two sets of tasks running separately? Or they point to the same tasks?

This is actually a good question, and it depends on the source sequence on which you call ToList. If temp is a collection of running tasks (as in your case), then ToList simply creates a copy of their references, meaning your new list would point to the same set of tasks.

However, if temp constitutes a sequence of tasks that have yet to be instantiated (due to deferred execution), then you would get a new set of tasks each time you call ToList. Here is a simple example (using ToArray, which has the same effect as ToList):

int count = 0;

var tasks = Enumerable.Range(0, 10).Select(_ => 
    Task.Run(() => Interlocked.Increment(ref count)));

// tasks = tasks.ToArray();   // deferred vs. eager execution

Task.WaitAll(tasks.ToArray());
Task.WaitAll(tasks.ToArray());

Console.WriteLine(count);

If you run the code above, the final result will be 20, meaning that two batches of tasks were run (one for each ToArray call). However, if you uncomment the line that enables eager execution, the final result will become 10, indicating that the subsequent ToArray calls only copy the references, rather than spawn new tasks.

这篇关于难道tasks.ToList()创建一个包含新复制的任务列表或列表是指在相同的任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆