2016-05-17 14 views
1

私はいくつかの問題を解決するプログラムを用意しています。素晴らしいGUIでそれを監視したいと思っています。 GUIの場合、Gtkを選択しました。これは、専用スレッドでmainGUIループを実行する必要があることを意味し、残りのプログラムは別のスレッドを占有します。私は自分のプログラムと他のスレッドとの間の通信がChanを使って一方向に流れると考えました。私はさらに、作業者からの通知時にGUIを更新するためにFRPを使用することにしました(独自のスレッドの元のプログラムのロジック)。だから、私は1つのスレッドがアクションを実行する監視スレッド(それらを表示する)に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


は、私は、メッセージの反応性取扱い、すなわちイベントのネットワークを記述し、c :: Chan (IO())内の各メッセージは、明示的に(おそらく、ブロッキング)スレッドに読み込まれ

main = do 
    c <- newChan 

    forkIO . forever . join . readChan $ c 

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

から移動したい明確にするために、/behaviorsを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" 
+0

これは役立つかもしれない:https://wiki.haskell.org/Haskell_for_multicores#Message_passing_channels – jkeuhlen

+0

おかげで、私はしかしFRPの一部ではなく、チャンネルより困惑しています。 – jakubdaniel

答えて

2

結果の動作は、イベントのネットワークが処理する時に更新されますfromPoll状態

のドキュメント入力イベント。

イベントがないので、それが更新されることはありません。 fromPollは、変更可能なデータを読み込み、ネットワークを更新するのではなく、すばやく汚い方法として意図されています。むしろ、ドキュメントではfromChangesを使用することを推奨しています。しかし、われわれはEventが欲しいので、newEventを使ってみましょう。Eventを作成し、Handler(これは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" 
関連する問題