如何在不“运行两次”或“失败”的情况下同时运行一些线程?我会以一个例子解释我的问题:
private int count = 0;
private HashSet<int> hs_pages = new HashSet<int>();
for (int page = 1; page <= 10; page++)
{
Thread thread = new Thread(unused => my_method(page));
thread.Name = "Thread - " + page.ToString();
thread.Start();
}
while(count < 10)
{
}
并将my_method()
实现为:
public void my_method(int page)
{
if (hs_pages.Add(page))
{
count++;
//My Codes
}
else
{
MessageBox.Show("this is duplicate of page : " + page.ToString());
}
}
在运行这段代码之后,我发现有些页面(1-10页)不运行,有些页面运行两次。
因此,while()
永远不会因为这些重复和失败而结束。
我怎样才能修复那些重复和失败?
我对失败的意义不是“错误”,我的意思是,例如,my_method(4)
从未运行过,而重复的意思是my_method(3)
运行了两次。
我知道还有其他方法,如Parallel.ForEach
,但我想学习如何使用线程类。
发布于 2013-10-11 11:22:54
你要关闭循环变量。
闭包关闭于变量,而不是值。您正在创建的lambda不是在循环主体中获取page
当前值的副本,而是创建对该变量的引用,当匿名方法在将来的某个时候实际执行时,它将访问该变量的值。当执行实际发生时,循环已经继续并增加了一些次(我们不知道有多少次,这将取决于线程的调度方式)。
创建一个page
的副本,该副本位于循环主体的局部,这样每个闭包都位于不同的变量上,而不是正在发生变异的单个变量:
for (int page = 1; page <= 10; page++)
{
int pageCopy = page;
Thread thread = new Thread(unused => my_method(pageCopy , count));
thread.Name = "Thread - " + pageCopy.ToString();
thread.Start();
}
而且,您不应该忙着等待所有线程完成;这极大地浪费了系统资源,在while循环中花费了大量的CPU时间。相反,在创建这些对象时,将创建的所有Thread
对象放入一个List<Thread>
中,然后在完成后再次遍历列表,然后调用它们上的Join
等待它们完成。
https://stackoverflow.com/questions/19325669
复制