Delphi 10:同时运行任务的正确方法 [英] Delphi 10: Correct way to run tasks simultaneously

查看:343
本文介绍了Delphi 10:同时运行任务的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习如何使用delphi并行库而不是TThread.我有许多要同时运行的任务.每个任务最多都是在等待某个事件,而在等待时,我想将执行权传递给其他任务. 这是我的示例代码:

I'm trying to learn how to use delphi parallel library instead of TThread. I have many tasks that I want to run simultaneously. Each task is most time waiting for some event, while its waiting, I'd like to pass excecution to another tasks. Here is my sample code:

type

TObj = class
  pos:     integer;
  Done:    boolean;
  Constructor Create;
  procedure DoWork(Sender: TObject);
end;

var

Objects :   array [0..39] of TObj;
tasks :     array of ITask;

constructor TObj.Create;
begin
  pos:=0;
  DOne:=false;
end;

procedure TObj.DoWork(Sender: TObject);
begin
  repeat
    inc(pos);
    sleep(100);
  until Done;
end;

procedure TForm1.StartClick(Sender: TObject);
var
  i:  integer;
begin
  Setlength (tasks ,Length(Objects));
  for i:=0 to Length(tasks)-1 do begin
    Objects[i]:=TObj.Create; 
    tasks[i] := TTask.Create(Objects[i],Objects[i].DoWork);
    tasks[i].Start;
  end;
  sleep(5000);
  Memo1.Lines.Clear;
  for i:=0 to Length(tasks)-1 do begin
    Objects[i].Done:=true;
    Memo1.Lines.Add(IntToStr(Objects[i].pos));
  end;
end;

我启动了N个任务,每个任务应在100毫秒内将其计数器增加1.然后我等待5秒钟,然后检查任务的值.我期望它们至少几乎相等,但是实际的Memo1的输出显示前12个值大约为50,其他4个值大约为20-30(我正在运行Ryzen 1600),我感到奇怪的是,最小的值都是0!

I start N Tasks, each should increase its counter by 1 in 100ms. Then I wait 5 sec and check task's values. I excpect them to be at least nearly equal, but real Memo1's output shows first 12 values are about 50, the other 4 values about 20-30 (I'm running Ryzen 1600), and whats strange fo me that the least values are all 0!

显然,在40秒中,只有40个任务中有16个任务在5秒内至少执行了一次,所以我想知道如何替换sleep(100)来将执行权实际传递给其他任务?

Evidently only 16 tasks from 40 actually excecuted atleast once in 5 seconds, so I would like to know how I can replace sleep(100) to actually pass excecution to another tasks?

推荐答案

仅因为您启动了N个任务,并不意味着N个任务将同时运行.如果需要的话,请坚持使用TThread.

Just because you start N number of tasks does not mean that N number of tasks will be running concurrently. If you want that, stick with TThread.

PPL使用内部线程池为TTask对象提供服务,并且该池根据您已安装的许多CPU和实际运行的任务数量进行自我调节. PPL文档:

The PPL uses an internal thread pool to service the TTask objects, and that pool is self-throttling and self-adjusting based on now many CPUs you have installed and how many tasks are actually running. This is explained in the PPL documentation:

RTL提供了并行编程库(PPL),使您的应用程序能够利用跨多个CPU设备和计算机的工作来使任务并行运行. PPL包括许多用于运行任务,加入任务,等待任务组等的高级功能,以进行处理. 为此,有一个线程池会自动进行自我调整(基于CPU的负载),因此您不必在意为此目的创建或管理线程.

如果创建的任务多于池中具有线程的任务,则某些任务将等待较早的任务完成其工作.当给定线程完成任务时,它将检查等待的任务,如果找到则运行该任务,然后重复进行直到没有其他任务可以运行为止.将其乘以池中的线程数和队列中的任务数.

If you create more tasks than the pool has threads, some tasks are going to be waiting for earlier tasks to finish their work. When a given thread finishes a task, it checks for a waiting task, and if found then runs it, repeating until there are no more tasks to run. Multiply that by the number of threads in the pool and the number of tasks in the queue.

因此,在任何给定时间都只会运行少量任务,因此可能需要一段时间才能完成您排队的所有任务.

So, there will only ever be a handful of tasks running at any given time, and so it may take awhile to get through all of the tasks that you queue up.

如果要对线程池进行更多控制,则必须创建一个 TThreadPool 对象,根据需要设置其MinWorkerThreadsMaxWorkerThreads属性,然后将该对象传递给具有APool输入参数的TTask构造函数之一.默认情况下,MinWorkerThreads设置为TThread.ProcessorCountMaxWorkerThreads设置为TThread.ProcessorCount * 25.

If you want more control over the thread pooling, you have to create a TThreadPool object, set its MinWorkerThreads and MaxWorkerThreads properties as desired, and then pass that object to one of the TTask constructors that has an APool input parameter. By default, the MinWorkerThreads is set to TThread.ProcessorCount, and the MaxWorkerThreads is set to TThread.ProcessorCount * 25.

这篇关于Delphi 10:同时运行任务的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆