【问题标题】:Starting tasks again重新开始任务
【发布时间】:2019-04-05 19:27:13
【问题描述】:

我最近开始了 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 过程重新启动工作任务时,什么也没有发生。 有人可以告诉我我错过了哪一点。

【问题讨论】:

    标签: ada multitasking


    【解决方案1】:

    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 成对调用。

    【讨论】:

      【解决方案2】:

      一个任务只运行到它的主要语句序列结束(忽略各种技术细节)。

      如果你想让一个任务做某事,然后暂停直到它接收到一个外部触发器,你应该在任务主体中的语句周围放置一个循环。

      【讨论】:

      • 第一次执行后不能重启任务吗?我不想在暂停的任务上浪费 CPU 时间。任务应该完成他的工作,完成并在一段时间后从头开始
      • 没有。但是您可以拥有一个任务类型,并根据需要创建该类型的新任务。等待任务不占用CPU,所以我的建议很难说是浪费CPU时间。
      • 好的。感谢您的帮助
      猜你喜欢
      • 2011-07-11
      • 1970-01-01
      • 1970-01-01
      • 2021-06-17
      • 1970-01-01
      • 1970-01-01
      • 2022-11-23
      • 2013-01-12
      • 1970-01-01
      相关资源
      最近更新 更多