2015-07-02 42 views
0

我创建的一个任务似乎并没有放弃控制,因此主线程将运行。我不知道为什么。由于这是我第一次尝试在Ada中使用多线程(在使用GtkAda的GNAT下),我相信我在这里错过了一些基本原则。使用GtkAda进行Ada线程切换

我主要如下所示:

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是这个,它调用Redisplay_Item_And_Get_Sw中对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并在主任务中继续该代码。

我已经在调试器中验证了这一点。

我认为每个循环中的延迟都会暂停相关任务,但我显然不能正确理解它。这段代码是否可以修复而没有太多的改变? (我希望我能够正确执行任务的基本框架。)什么是缺失或错误的?

+0

我还没有这样的设计实验(围棋,不是阿达,但同样的原理/技术),足以知道为什么你的代码不起作用,或者为什么延迟不起作用。我会说你将不得不做的是把它分成两个任务。一个简单的调用'gtk_main()'并处理所有的GUI东西。另一个具有所有'Gui_Do_Thing'的东西,使用'g_idle_add()'或'gdk_threads_add_idle()'函数(两者之一)来告诉'gtk_main()'任务来完成这件事。我不知道Ada等价物会是什么或者如何写出它们,对不起。祝你好运! – andlabs

回答

3

我看到的问题是,Gtkada分层在非Ada产品Gtk之上,不支持Ada的任务模型。

根据Dmitry Kazakov's "GTKAda Contributions" library

GTK +被称为是不安全的任务。特别是,所有的调用都需要从同一个任务(线程)中完成。

我没有更好的建议,而不是在那个链接“与GTK + 1任务处理”,其中包含1.1节中的例子看他的文件,特别是第一部分, - 如果你发现它有用 - 下载和使用他的支持库。

(如果人们认为这应该是一个评论,我会让它如此)

+0

[*§9.1保护类型*](http://www.adaic.org/resources/add_content/standards/95rat/rat95html/rat95-p1-2.html#9)是一个不错的选择;还要考虑'Gtk.Main.Timeout'进行定期渲染。 – trashgod