我尝试调用一个任务100次,但是它不起作用,看来我应该创建100个条目来执行此操作。所以,请您提供一些建议吗?
我正在学习如何使用Ada任务:-)
explain (analyze, verbose)
select *
from generate_series(1,50000) AS w
cross join generate_series(current_date,current_date+30,interval '1 day') AS v;
QUERY PLAN
Nested Loop (cost=0.02..20010.02 rows=1000000 width=12) (actual time=3.237..3128.123 rows=1550000 loops=1)
Output: w.w, v.v
-> Function Scan on pg_catalog.generate_series w (cost=0.00..10.00 rows=1000 width=4) (actual time=3.210..35.472 rows=50000 loops=1)
Output: w.w
Function Call: generate_series(1, 50000)
-> Function Scan on pg_catalog.generate_series v (cost=0.02..10.02 rows=1000 width=8) (actual time=0.001..0.021 rows=31 loops=50000)
Output: v.v
Function Call: generate_series((('now'::cstring)::date)::timestamp with time zone, ((('now'::cstring)::date + 30))::timestamp with time zone, '1 day'::interval)
Planning time: 0.046 ms
Execution time: 4103.113 ms
E:\ Ada代码\ Simple \ obj \ main.exe 哈哈
提高了TASKING_ERROR [2019-06-03 17:55:17]进程退出,状态为1,经过时间:01.00s
答案 0 :(得分:3)
您的问题是任务将在接受第一个集合点后运行到完成。您可以通过在任务正文中添加循环来避免这种情况:
task body test1 is
begin
loop
accept start;
Put_Line("Haha");
end loop;
end test1;
(实际上,大多数任务都会有这样的循环)
该任务现在具有无限循环,因此下一步是确保您的任务在主程序完成后终止。在这种情况下,您可以使用选择性接受:
task body test1 is
begin
loop
select
accept start;
or
terminate;
end select;
Put_Line("Haha");
end loop;
end test1;
答案 1 :(得分:2)
通常,与启动另一个任务相比,调用任务条目,将任何所需的数据传入或传出任务比调用另一个任务效率更高。开始和终止任务涉及不小的开销。 为任务调用任务条目的另一种方法是使用受保护的对象实现生产者-消费者模式。
以下生产者-消费者示例创建三个生产者和一个消费者。每个生产者将500,000条消息写入共享队列。消费者消耗生产者产生的所有消息。
------------------------------------------------------------------
-- Producer / Consumer example using 3 producers and 1 consumer --
-- Matches the number of tasks to a 4-core processor --
------------------------------------------------------------------
with Ada.Containers.Synchronized_Queue_Interfaces;
with Ada.Containers.Unbounded_Synchronized_Queues;
with Ada.Text_IO; use Ada.Text_IO;
With Ada.Calendar; use Ada.Calendar;
use Ada.Containers;
procedure PC_v3 is
package Integer_Interface is new
Synchronized_Queue_Interfaces(Element_Type => Integer);
package Unbounded_Integer_Queues is new
Unbounded_Synchronized_Queues(Queue_Interfaces => Integer_Interface);
My_Queue : Unbounded_Integer_Queues.Queue;
Num_Producers : Constant := 3;
Max_Produced : constant := 500_000;
Empty_Queue : constant Count_Type := 0;
Start_Time : Time := Clock;
-- The Counter protected object below is used to count the number of
-- completed producers. This allows the consumer to know when all the
-- data has been processed.
---------------------------------------------------------------------
protected Counter is
Procedure Task_Done;
function All_Done return boolean;
private
Count : Natural := 0;
end Counter;
protected body Counter is
procedure Task_Done is
begin
Count := Count + 1;
end Task_Done;
function All_Done return boolean is
begin
return Count = Num_Producers;
end All_Done;
end Counter;
-- Define the producer task type.
-- Producer is being defined as a task type to allow multiple instances
-- of the producer to be easily created.
------------------------------------------------------------------------
task type Producer;
Task body Producer is
Value : Positive := 1;
Finis_Time : Time;
begin
loop
My_Queue.Enqueue(Value);
Value := Value + 1;
if Value > Max_Produced then
Counter.Task_Done;
Finis_Time := Clock;
Put_Line("Producer completed in" &
Duration'Image(Finis_Time - Start_Time) &
" seconds");
exit; -- exit the loop within the Producer task
end if;
end loop;
end Producer;
Read_Value : Integer;
Done_Time : Time;
-- Create an array of producers. There are Num_Producers in this
-- array. The Producer tasks start executing as soon as they are
-- instantiated in the array.
----------------------------------------------------------------
The_Producers : array(1..Num_Producers) of Producer;
begin
-- Process the values in My_Queue until all producers are completed
-- and the queue is empty.
-- The program main task is being used as the consumer task.
loop
My_Queue.Dequeue(Read_Value);
exit when Counter.All_Done and then My_Queue.Current_Use = Empty_Queue;
end loop;
-- Record the time stamp when all queue processing is done
Done_Time := Clock;
-- print out the execution statistics
Put_Line("Queue element peak use:" & Count_Type'Image(My_Queue.Peak_Use));
Put_Line("Elapsed time (seconds):" & Duration'Image(Done_Time - Start_Time));
end PC_V3;
如您所见,使用者一直运行直到所有数据被消耗为止,而不知道有多少生产者正在运行或有多少消息正在产生。这比让每个生产者为产生的每条消息都呼叫一个消费者要有效得多。