我在Windows窗体C#应用程序中有这些代码:
private void button7_Click(object sender, EventArgs e)
{
ThreadStart starter = delegate { thread_func(2, 1000000); };
thread1_thread = new Thread(starter);
starter = delegate { thread_func(1000000, 2000000); };
thread2_thread = new Thread(starter);
starter = delegate { thread_func(2000000, 3000000); };
thread3_thread = new Thread(starter);
starter = delegate { thread_func(3000000, 4000000); };
thread4_thread = new Thread(starter);
thread1_thread.Start();
thread2_thread.Start();
thread3_thread.Start();
thread4_thread.Start();
}
void thread_func(decimal input1,decimal input2)
{
for (; input1 < input2; input1++)
{
threadNumbers_list.Add(input1);
if (input1 % 2 != 0)
{
if (isPrime_func(input1))
{
PrimeNumbers_decimal_list.Add(input1);
}
}
}
}
public static Boolean isPrime_func(decimal number)
{
decimal boundary = (decimal)Math.Floor(Math.Sqrt((double)number));
if (number == 1) return false;
if (number == 2) return true;
for (decimal i = 2; i <= boundary; ++i)
{
if (number % i == 0) return false;
}
return true;
}
每次我点击该按钮,我都会得到不同的结果。我尝试了很多东西,但无法弄清楚为什么会这样。即使是较低的范围也会发生。例如,在100个数字的范围内,它总是给出相同的结果。 有一段时间我的列表计数达到283138,有时候是283131和其他近似数字。
另一个奇怪的是,当我评论检查偶数时,操作比这个模式花费的时间更短。怎么了?
答案 0 :(得分:2)
当多个线程访问列表时,该列表必须是线程安全的,否则您将遇到很多问题。
.NET提供了thread-safe collections类ConcurrentQueue<T>
之类的一些supports data parallelism via the Parallel
class。
附注:请考虑使用Tasks
代替线程。此外,.NET框架http://codesheet.org/codesheet/wOHDXFju。考虑使用这样的类。
关于不检查数字是否均匀时的性能,我在本地进行了测试,得到了以下数字:
因此,这与您的测量值不符。这可能是由您测量的方式引起的。我用这样的Stopwatch
来衡量:
//...
Stopwatch sw = Stopwatch.StartNew();
thread1_thread.Start();
thread2_thread.Start();
thread3_thread.Start();
thread4_thread.Start();
thread1_thread.Join();
thread2_thread.Join();
thread3_thread.Join();
thread4_thread.Join();
long result = sw.ElapsedMilliseconds;
//...
顺便说一句,你可以做的就是为你节省一些执行时间:
为List<T>
方法中的每个线程创建一个普通的thread_func
实例,这样就不会出现多线程问题。然后在循环结束后,您可以从本地列表更新主列表。只更新主列表必须是线程安全的。在这种情况下,我希望主列表是正常的List<T>
,并且您使用lock
关键字来同步对它的访问,因为您只需要更新它4次(线程数)。