我正在编写一个程序,根据用户提供的某些条件显示mandelbrot集。由于计算时间很长(超过500毫秒),我决定使用多个线程。没有任何以前的经验,我已经设法通过使用System.Threading.Tasks类来完成它,它运行得很好。我唯一不喜欢的是每次生成mandelbrot时,线程都被创建然后被销毁。
这是一个如何运作的例子。每次调用该方法时,它都会创建线程(Tasks)。
for (int i = 0; i < maxThreads; i++) {
int a = i;
tasks[a] = Task.Factory.StartNew(() => generateSector(a));
}
我真的不知道它会如何影响性能,但看起来创建和销毁线程的时间非常昂贵,并且让线程准备就绪并等待触发消息会更高效< / strong>,完成后再回到等待状态。可能是以下示例代码有助于理解这个想法。
for (int i = 0; i < maxThreads; i++)
tasks[i].sendMessage("Start"); // Tells the running thread to begin its work
所以每个线程都会执行一个等待的无限循环,直到需要它们进行计算。然后,它将继续等待。像这样:
// Into the method that a thread executes
while(true) {
Wait(); // Waits for the start signal
calculate(); // Do some calculations
} // Go back to waiting
这会更有效吗?有没有办法做到这一点?
答案 0 :(得分:3)
保持您的代码不变。
1)任务使用ThreadPool线程,因此没有问题
2)“我真的不知道这会影响表现” - 这是你应该开始的地方。测量前切勿优化。你有性能问题吗?你的代码运行缓慢吗?我想不,所以你不应该被打扰。
答案 1 :(得分:1)
当您使用Task.Factory.StartNew(...)
时,you are not必然会创建并销毁线程。任务库使用ThreadPool
来执行此操作,因此您无需自行管理,就像您自己创建new Thread()
s一样。
答案 2 :(得分:0)
听起来您正在尝试使用一组线程并设置一个系统来计划在这些线程上运行的工作。这是一个好主意,但实际上,它太好了,它内置在.NET框架中,您无需自己构建它。实际上,这正是任务的目的。
任务是Thread Pool上相对较轻的抽象,它由.NET运行时管理。线程是一种相对较重的操作系统构造,启动,停止和在线程之间进行上下文切换的开销有些昂贵。创建任务时,它计划该任务在池中的下一个可用线程上执行,.NET运行时将根据是否有工作排队等待线程等待来自动增加和减小池的大小。执行。您可以根据需要自定义minimum和maximum线程计数,但这通常不是必要的。
因此,通过简单地创建在单个工作单元的生命周期内存在的短期任务,它们已经可以在托管的实际线程集合上运行您的工作。