我写一个开启N多个task子任务的传参方法,但结果不对,求教

我的测试环境是基于.net 4.5测试的,但发现有问题,请大神们帮忙指导一下,谢谢:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

namespace WindowsFormsApp1

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

/// <summary>

/// 测试开启N多个子task任务并实现将i作为参数传入,但是结果不对头呢,这个怎么应该怎么处理啊?

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void button1_Click(object sender, EventArgs e)

{

Task<string[]> parent = new Task<string[]>(state => {

Console.WriteLine(state);

string[] result = new string[100000];

for (int i = 0; i < result.Length; i++)

{

new Task(() => { result[i] = "我是子任务::"+i.ToString(); Console.WriteLine(result[i]); }, TaskCreationOptions.AttachedToParent).Start();

}

//创建并启动子任务

//new Task(() => { result[1] = "我是子任务2。"; }, TaskCreationOptions.AttachedToParent).Start();

return result;

}, "我是父任务,并在我的处理过程中创建多个子任务,所有子任务完成以后我才会结束执行。");//任务处理完成后执行的操作

parent.ContinueWith(t => {

//Array.ForEach(t.Result, r => Console.WriteLine(r));

});//启动父任务

parent.Start();//等待任务结束 Wait只能等待父线程结束,没办法等到父线程的ContinueWith结束//parent.Wait();

Console.ReadLine();

}

}

}

运行结果如下:
image
发现这个传参的有问题,我想把i这个参数传入进去执行,这个问题应该怎么解决呀?求指导,谢谢!

回答:

要用闭包呀。

Task<string[]> parent = new Task<string[]>(state => {

Console.WriteLine(state);

string[] result = new string[100000];

for (int i = 0; i < result.Length; i++)

{

// 【这里改了】

new Task((state) => { int i = (int)state; result[i] = "我是子任务::"+i.ToString(); Console.WriteLine(result[i]); }, i, TaskCreationOptions.AttachedToParent).Start();

}

//创建并启动子任务

//new Task(() => { result[1] = "我是子任务2。"; }, TaskCreationOptions.AttachedToParent).Start();

return result;

}, "我是父任务,并在我的处理过程中创建多个子任务,所有子任务完成以后我才会结束执行。");//任务处理完成后执行的操作

回答:

经典的拉姆达表达式捕捉循环变量的问题。

解决方案有人已经给出来了,但不是靠“用闭包”解决的。

捕捉的循环变量分为两种,一种 for 循环的,一种是 foreach 循环的。如果捕捉的是 for 循环变量,也就是题主所说的这种情况,肯定会出这种问题。如果捕捉的是 foreach 循环变量,在 C#5.0 之前是有这种问题的,解决方式同 for 循环的一样。但是到 C#5.0 之后就没有这种问题了。

题外话,“闭包” 是编译器生成的一个 sealed 类,被拉姆达捕捉的变量,会成为这个闭包类的实例字段,而所有之前使用那个变量的地方,都变成了使用实例字段。

以上是 我写一个开启N多个task子任务的传参方法,但结果不对,求教 的全部内容, 来源链接: utcz.com/p/190407.html

回到顶部