Delphi并非所有线程都同时执行

时间:2014-07-21 09:59:23

标签: multithreading delphi

我有以下情况:

我正在编写的程序模拟多个空中网络。现在我已经编写了它,以便每个模拟都有自己的线程和自己的数据。这样就不会有数据污染,每个线程都是完整的多任务处理安全。我为每个线程实现了delphi的本机TThread类。

该程序有一个主线程。然后它为每个网络创建多个子线程(我当前的测试用例有6个)。但是每个子线程还有4个额外的线程,因为它的网络有多个布局。总共我有31个线程,但只有24个线程正在积极处理。所有线程都以挂起模式创建,以便我可以手动启动它们。

我运行的计算机是一台i5笔记本电脑,因此它有4个线程(2个物理核心+ 2个HT)。在生产环境中,这将在服务器上运行,因此它们将具有更强的处理能力。

现在在主程序线程中,我在执行线程的for循环之后添加了一个断点。这不会立即触发。看着Delphi的调试控制台,看起来它一次只能主动运行4个线程。一旦退出,它就会启动另一个线程。

线程中的模拟很难优化,需要一些循环才能完成模拟。每个循环都需要前一个循环的数据。但每个模拟完全独立于下一个,因此该程序是螺纹和管道衬里的绝佳候选。

现在我的问题是为什么它只启动4个线程而不是代码指定的所有线程?

编辑添加了一些代码

主程序

    for i := 0 to length(Solutions)-1 do
    begin
        Solutions[i].CreateWorkers;  //Setup threads 
    end;
    for i := 0 to length(Solutions)-1 do
    begin
        Solutions[i].Execute;   //start threads
    end;
end;

isSolversBusy := false;    //breaking point doesn't trigger here

第1级线程

procedure cSolution.Execute;
var
i : integer;
lIsWorkerStillBusy : boolean;
begin
    lIsWorkerStillBusy := true;
   for i := 0 to length(Workers)-1 do
    begin
        Workers[i].Start;
    end;
    while (lIsWorkerStillBusy) do
    begin
        lIsWorkerStillBusy := false;
        for i := 0 to length(Workers)-1 do
        begin
            if Workers[i].IsCalculated = false then
            begin
                lIsWorkerStillBusy := true;
            end;
        end;
        sleep(100);
    end;
    FindBestNetwork;
    IsAllWorkersDone := true;
end;

第二级线程

procedure cWorker.Execute;
begin
    IsCalculated := false;
    Network.UpdateFlows;
    Network.SolveNetWork;  //main simulation work
    CalculateTotalPower;
    IsCalculated := true;
end;

编辑2

我创建它们的原因全部被暂停是因为我将它们存储在一个数组中,在我启动它们之前,我首先创建了worker和它们的属性。我正在模拟空中网络场景。每个解决方案都是不同的布局,而每个工作者都是运行该布局的不同方式。

我必须首先计算所有工人的启动属性,然后再启动它们。在后面的视线中我可以修改代码来在线程中执行此操作。它目前发生在主线程中。线程的创建发生在我粘贴的代码片段之前。

我将它们全部保存在线程中的原因是我需要评估每个线程的结果。

1 个答案:

答案 0 :(得分:14)

这是你的问题:

for i := 0 to length(Solutions)-1 do
begin
    Solutions[i].Execute;   //start threads
end;

启动线程 - 这是在调用线程中执行Execute方法。事实上,你一次只运行4个线程,你甚至没有运行一个 - 所有这些工作都将在主线程上顺序完成。要恢复暂停的主题,您必须使用Solutions[i].Start

Execute的{​​{1}}方法是在TThread 自动创建的工作线程上执行的特殊方法。创建TThread时,此方法会自动在TThread创建的工作线程上运行。如果你创建了挂起的线程,那么它只是等待你在开始这项工作之前唤醒线程。调用TThread的{​​{1}}方法就是实现这一点 - 触发底层工作线程开始执行.Start方法。

否则,TThread方法和.Execute的所有其他方法与属于某个类的任何其他常规方法没有区别。它们可以在任何直接调用它们的线程上执行。

在这种情况下,在创建和执行工作线程之间的主线程中,您似乎没有做任何额外的工作。在这种情况下,除非您明确需要它,否则您可以简单地创建未挂起的线程,并让它们在创建时自动执行。