2016-05-17 5 views
1

У меня есть программа, которая решает некоторые проблемы, и я решил, что хочу отслеживать в хорошем графическом интерфейсе, что он делает. Для 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 msg и receiving 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" 
+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" 
Смежные вопросы