【发布时间】:2015-07-02 05:18:59
【问题描述】:
我创建的任务似乎没有放弃控制权以便主线程运行。我不确定为什么。由于这是我第一次尝试在 Ada 中使用多线程(在带有 GtkAda 的 GNAT 下),我确信我在这里遗漏了一些基本原则。
我的主要看起来像这样:
procedure Main is
begin
Test_Gui.Gui_Task.Gui_Initialize;
Test_Gui.Simple_Switch_Test;
Msg("Done");
end;
在 Test_Gui 包中,规范和正文代码如下所示:
task type Gui_Type is
entry Gui_Initialize;
entry Gui_Reset_SwitCh_To_1;
entry Gui_Display_Message(Message : String);
entry Gui_Write_Debug;
end Gui_Type;
Gui_Task : Gui_Type;
和
task body Gui_Type is
begin
loop
select
accept Gui_Initialize do
Initialize;
end Gui_Initialize;
or
accept Gui_Reset_Switch_To_1 do
Reset_Switch_To_1;
end Gui_Reset_Switch_To_1;
or
accept Gui_Display_Message (Message : in String) do
Display_Message(Message);
end Gui_Display_Message;
or
accept Gui_Write_Debug do
Debug_Label.Set_Label(Debug_Label_Text);
end Gui_Write_Debug;
else
Gdk.Threads.Enter;
Dead := Gtk.Main.Main_Iteration;
Gdk.Threads.Leave;
delay 0.01;
end select;
end loop;
end Gui_Type;
从 main 调用的第二个方法 Simple_Switch_Test 是 this,它从 Redisplay_Item_And_Get_Switches 调用对 GUI 任务的调用。
procedure Simple_Switch_Test is
Text : String(1..80) := (others => ' ');
Msg : String(1..16);
begin
loop
Count := Count + 1;
Copy_String(Integer'Image(Count), Text);
for I in 1..16 loop
Msg(I) := Text(I);
end loop;
Redisplay_Item_And_Get_Switches(Msg);
Copy_String("some stuff.."), Debug_Label_Text );
Gui_Task.Gui_Write_Debug;
delay 0.01;
end loop;
end;
初始化工作和 GUI 功能,即使它的回调工作。但是,在第一次从 Simple_Switch_Test 调用 Redisplay_Item_And_Get_Switches 将代码放入 GUI 任务循环后,它不会离开 else 子句,除了处理回调。
因此,它永远不会调用 Gui_Task.Gui_Write_Debug 并在主任务中继续该代码。
我已经在调试器中验证了这一点。
我认为每个循环中的延迟会暂停相关任务,但我显然没有正确理解它。此代码是否可以在没有太多更改的情况下修复? (我希望我能正确实施任务的基本框架。)它有什么缺失或错误?
【问题讨论】:
-
我还没有尝试过这种设计(在 Go 中,不是 Ada,但相同的原理/技术)足以知道为什么你的代码不起作用,或者为什么延迟不起作用。我会说你要做的就是把它分成两个任务。只需调用
gtk_main()并处理那里的所有GUI 内容。另一个拥有你所有的Gui_Do_Thing东西,使用g_idle_add()或gdk_threads_add_idle()函数(两者之一)告诉gtk_main()任务来做这件事。我不知道 Ada 等价物是什么或如何编写它们,抱歉。祝你好运!
标签: multithreading gtk ada