我写一个开启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();
}
}
}
运行结果如下:
发现这个传参的有问题,我想把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