来自线程间共享通信通道的事件

Events from shared communication channel between threads

我有一个程序可以解决一些问题,我决定要在漂亮的 GUI 中监视它的功能。对于 GUI,我选择了 Gtk,这意味着我需要 运行 mainGUI 在专用线程中循环,我的程序的其余部分将占用不同的线程。我认为我的程序和另一个线程之间的通信将使用 Chan 朝一个方向流动。我进一步决定使用 FRP 根据工作人员的通知更新 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 元素互连的 events/behaviours 网络,然后让线程执行 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"

fromPoll 的文档指出

The resulting Behavior will be updated on whenever the event network processes an input event.

由于没有活动,所以永远不会更新。 fromPoll 旨在作为一种快速而肮脏的方式来读取可变数据,而不是更新网络。相反,文档建议我们使用 fromChanges。但是因为我们或者,因为我们无论如何都想要 Event,所以让我们使用 newEvent,这似乎很合适:它允许我们创建一个 Event,我们通过调用 [=17] 向其添加值=](这是 a -> IO () 的别名)。

import Control.Concurrent
import Control.Monad

import Reactive.Banana
import Reactive.Banana.Frameworks

main = do

    c <- newChan

    network <- compile $ do
      (event, handler) <- newEvent
      liftIO $ forkIO $ forever (readChan c >>= handler)
      reactimate event

    forkIO $ actuate network

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