线程之间的共享通信通道中的事件

时间:2016-05-17 13:40:59

标签: multithreading haskell reactive-banana

我有一个解决了一些问题的程序,我决定在一个漂亮的GUI中监视它的作用。对于GUI,我选择Gtk,这意味着我需要在专用线程中运行mainGUI循环,我的程序的其余部分将占用不同的线程。我认为我的程序和其他线程之间的通信将使用Chan向一个方向流动。我进一步决定使用FRP来更新来自worker的通知的GUI(原始程序在其单独的线程中的逻辑)。所以我尝试编写一个简单的线程示例,其中一个线程将IO个动作发送到执行操作的监视线程(显示它们)。这是我的尝试:

import Control.Concurrent
import Control.Monad

import Reactive.Banana
import Reactive.Banana.Frameworks

main = do
    c <- newChan

    forkIO $ do
        actuate <=< compile $ reactimate'
                            <=< changes
                            <=< fromPoll
                            $ readChan c

    forever $ do
        threadDelay 3000000
        putStrLn "sending msg"
        writeChan c $ putStrLn "receiving msg"

这显然不起作用(它只打印sending msg)否则我不会在这里。我究竟做错了什么?我需要一个与投票相同的不同事件吗?怎么做?

我期待一些文本副本的交错:sending msgreceiving msg

澄清我想要离开

main = do
    c <- newChan

    forkIO . forever . join . readChan $ c

    forever $ do
        threadDelay 3000000
        putStrLn "sending msg"
        writeChan c $ putStrLn "receiving msg"

其中c :: Chan (IO ())中的每个消息都在线程中明确地读取(可能是阻塞),消息的反应性处理,即描述与GUI元素互连的事件/行为的网络,然后让线程执行GUI循环。网络需要处理通道中的轮询值和触发事件。

我正在寻找的解决方案(或类似的东西):

main = do
    (msgHandler, msgFire) <- newAddHandler

    forkIO $ do
        actuate <=< compile $ do
            eMsg <- fromAddHandler msgHandler

            reactimate $ putStrLn <$> eMsg

    forever $ do
        threadDelay 3000000
        putStrLn "sending msg"
        msgFire "receiving msg"

1 个答案:

答案 0 :(得分:2)

Value州的文档

  

只要事件网络处理输入事件,结果行为就会更新。

由于没有事件,因此永远不会更新。 observeSingleEventOfType旨在作为一种快速而肮脏的方式来读取可变数据,但不是为了更新网络。相反,文档建议我们使用fromPoll。但是,既然我们或者因为我们想要fromPoll,那么让我们使用newEvent,这似乎非常合适:它允许我们创建一个fromChanges,我们通过调用{{1}来添加值}(这是Event的别名)。

Event