并行任务的意外输出
Unexpected output on parallel tasks
我必须并行化现有代码。基本上,代码获取一个文件,对其进行处理并将结果保存在一个新文件中。我需要对一批文件进行这项工作。
所以,我做这个示例代码是为了查看我需要什么样的代码结构,但它运行起来很奇怪:
class Program
{
static void Main(string[] args)
{
Processor processor = null;
ProcessAsync(processor, 3);
}
static void ProcessAsync(Processor processor, int n)
{
IList<Task> tasks = new List<Task>();
for (int i = 0; i < n; ++i)
{
processor = new Processor(i);
tasks.Add(new Task(() => processor.Process()));
tasks[i].Start();
}
for (int i = 0; i < n; ++i)
{
tasks[i].Wait();
}
}
}
class Processor
{
private readonly int id;
public Processor(int id)
{
this.id = id;
}
public void Process()
{
Console.WriteLine(id.ToString("000") + ": " + "Processing...");
Thread.Sleep(1000);
Console.WriteLine(id.ToString("000") + ": " + "Processed!");
}
}
我期望这样的输出:
Task 000: Processing...
Task 001: Processing...
Task 002: Processing...
Task 000: Processed!
Task 001: Processed!
Task 002: Processed!
但我得到了这个结果:
Task 002: Processing...
Task 002: Processing...
Task 002: Processing...
Task 002: Processed!
Task 002: Processed!
Task 002: Processed!
为什么 processor
的 id
都是 002
?
忽略其他问题,这是一个捕获和接近问题
你可以搜索一下,网上有很多关于它的文章,这正是 CLR 和 lambda 的工作方式
修复只是创建一个新的局部变量
for (int i = 0; i < n; ++i)
{
var proc = new Processor(i);
tasks.Add(new Task(() => proc.Process()));
tasks[i].Start();
}
快速看一下,它似乎与变量作用域和将作用域折叠到 lambda 中有关。
试着改变你的循环,让它变成这样:
for (int i = 0; i < n; ++i)
{
tasks.Add(new Task(() => new Processor(i).Process()));
tasks[i].Start();
}
另外,请问Processor是否真的需要class,难道不是一个简单的方法吗?您传入处理器的逻辑有些奇怪,但随后为每个循环迭代创建一个新处理器。你真的想要那个吗?
我必须并行化现有代码。基本上,代码获取一个文件,对其进行处理并将结果保存在一个新文件中。我需要对一批文件进行这项工作。
所以,我做这个示例代码是为了查看我需要什么样的代码结构,但它运行起来很奇怪:
class Program
{
static void Main(string[] args)
{
Processor processor = null;
ProcessAsync(processor, 3);
}
static void ProcessAsync(Processor processor, int n)
{
IList<Task> tasks = new List<Task>();
for (int i = 0; i < n; ++i)
{
processor = new Processor(i);
tasks.Add(new Task(() => processor.Process()));
tasks[i].Start();
}
for (int i = 0; i < n; ++i)
{
tasks[i].Wait();
}
}
}
class Processor
{
private readonly int id;
public Processor(int id)
{
this.id = id;
}
public void Process()
{
Console.WriteLine(id.ToString("000") + ": " + "Processing...");
Thread.Sleep(1000);
Console.WriteLine(id.ToString("000") + ": " + "Processed!");
}
}
我期望这样的输出:
Task 000: Processing...
Task 001: Processing...
Task 002: Processing...
Task 000: Processed!
Task 001: Processed!
Task 002: Processed!
但我得到了这个结果:
Task 002: Processing...
Task 002: Processing...
Task 002: Processing...
Task 002: Processed!
Task 002: Processed!
Task 002: Processed!
为什么 processor
的 id
都是 002
?
忽略其他问题,这是一个捕获和接近问题
你可以搜索一下,网上有很多关于它的文章,这正是 CLR 和 lambda 的工作方式
修复只是创建一个新的局部变量
for (int i = 0; i < n; ++i)
{
var proc = new Processor(i);
tasks.Add(new Task(() => proc.Process()));
tasks[i].Start();
}
快速看一下,它似乎与变量作用域和将作用域折叠到 lambda 中有关。
试着改变你的循环,让它变成这样:
for (int i = 0; i < n; ++i)
{
tasks.Add(new Task(() => new Processor(i).Process()));
tasks[i].Start();
}
另外,请问Processor是否真的需要class,难道不是一个简单的方法吗?您传入处理器的逻辑有些奇怪,但随后为每个循环迭代创建一个新处理器。你真的想要那个吗?