我最近开始使用Ada编程,现在我被卡住了。 我创建了一个包含多个任务的程序。主要任务是管理传入通信,因此启动工作任务或将数据传输到工作任务。 工作任务都是相同类型但具有不同的标识符。 他们做他们的工作,并应该在那之后完成。例如:
task body Access_Protected is
begin
accept Start(foo: in Integer; foo2: out Integer)
do something
end Start;
while Go_loop loop
select
accept Quit do
Go_loop := false;
end Quit;
or
accept Insert(foo3: in Integer)
do something
if something = 0 then
Go_loop := false;
end if;
end Insert;
or delay 2.0;
end select;
end loop;
end Access_Protected;
我知道当Go_loop完成时应该终止工作任务。我对吗? 它可以启动任务一次,但是当主任务尝试通过调用Start过程重新启动工作任务时,没有任何反应。 有人可以告诉我我错过了哪一点。
答案 0 :(得分:3)
task
和子程序有些相关,因为当身体完成时,构造结束,也就是说构造以适当的end
结束;如果procedure
控件返回给调用者,则在function
的情况下引发异常PROGRAM_ERROR
,并且在task
控件的情况下线程“终止。
在您的特定问题中发生的事情似乎归结为以下几点:
Package Example is
Task Type Message_Task is
Entry Execute;
End Message_Task;
End Example;
Package Body Example is
Task Body Message_Task is
Use Ada.Text_IO;
Begin
accept Execute do
Put_Line( "Rendezvous!" );
end Execute;
delay 0.2; -- Stub delay.
Put_Line( "Finishing Task." );
-- Task Ends Here.
End Message_Task;
End Example;
--...
Test : Example.Message_Task;
--...
Test.Execute;
-- Test.Execute can't be accepted here because it can only accept "Execute"
-- the one time, as per the body's definition.
这个确实就像你的问题一样,是因为,同样一旦你说“X.Start(1,2)
”,另一次调用Start
就不会将任务执行的位置重置为该接受。
如果您希望任务“保持活力”以进行进一步处理,您可以选择以下两种方法之一。
选项1 - 设置'协议':
Package Example is
Task Type Message_Task is
Entry Initialization;
Entry Execute;
Entry Quit;
End Message_Task;
End Example;
Package Body Example is
Task Body Message_Task is
Use Ada.Text_IO;
Has_quit : Boolean := False;
Begin
Main:
loop
select
accept Initialization do
null;
end Initialization;
accept Execute do
null;
end Execute;
or
accept Quit do
Has_Quit := True;
end Quit;
end select;
Exit Main when Has_Quit;
end loop Main;
End Message_Task;
End Example;
选项2 - 允许终止。
Package Example is
Task Type Message_Task is
Entry Initialization;
Entry Execute;
End Message_Task;
End Example;
Package Body Example is
Task Body Message_Task is
Use Ada.Text_IO;
Has_quit : Boolean := False;
Begin
accept Initialization do
null;
end Initialization;
Main:
loop
select
accept Execute do
null;
end Execute;
or
terminate;
end select;
end loop Main;
End Message_Task;
End Example;
微妙的区别是选项2摆脱了Quit
条目,允许任务在terminate
替代上“休息”,而选项1在控制中更明确(在某些情况下需要) ,但需要Initialization
& Execute
成对调用。
答案 1 :(得分:2)
任务只有在到达主要语句序列的末尾才会运行(忽略各种技术细节)。
如果你想要一个任务做某事,然后暂停直到它收到一个外部触发器,你应该围绕你在任务体中的语句循环。