我正在使用WxHaskell以圖形方式顯示使用TCP(我使用Data.Binary解碼)通告狀態更新的程序的狀態。收到更新時,我想更新顯示。所以我希望GUI以異步方式更新它的顯示。我知道processExecAsync
異步運行命令行進程,但我不認爲這是我想要的。wxhaskell異步更新
回答
這是使用事務變量(即軟件事務內存)的粗略代碼。你可以使用IORef,MVar或其他許多構造。
main = do
recvFunc <- initNetwork
cntTV <- newTVarIO 0
forkIO $ threadA recvFunc cntTV
runGUI cntTV 0
上方啓動該程序,初始化網絡和共享變量cntTV
threadA recvCntFromNetwork cntTVar = forever $ do
cnt <- recvCntFromNetwork
atomically (writeTVar cntTVar cnt)
threadA
從網絡接收數據和寫入計數器的共享變量的新值。
runGUI cntTVar currentCnt = do
counter <- initGUI
cnt <- atomically $ do
cnt <- readTVar cntTVar
if (cnt == currentCnt)
then retry
else return cnt
updateGUICounter counter cnt
runGUI cntTVar cnt
runGUI
讀取共享變量,如果有變化將更新GUI計數器。僅供參考,runGUI線程不會在retry
上被喚醒,直到cntTVar
被修改,所以這不是一個CPU佔用輪詢循環。
在這段代碼中,我假設你有函數updateGUICounter
,initGUI
和initNetwork
。我建議你使用Hoogle來查找你還不知道的其他功能的位置,並學習一些關於每個模塊的知識。
感謝您的回答。這是我想到的。不幸的是,我們需要調用啓動事件循環的wxHaskell函數'start'。如果我們運行'start runGUI',那麼事件循環將永遠不會啓動。如果我們'forkIO'STM的東西,那麼GUI不會更新(至少在我嘗試時)。 – Alex 2010-07-05 20:48:27
我想出了一種似乎可行的hack。也就是說,使用事件計時器來檢查更新隊列:
startClient :: IO (TVar [Update])
startClient = /*Connect to server,
listen for updates and add to queue*/
gui :: TVar [Update] -> IO()
gui trdl = do
f <- frame [text := "counter", visible := False]
p <- panel f []
st <- staticText p []
t <- timer f [interval := 10, on command := updateGui st]
set f [layout := container p $ fill $ widget st, clientSize := (sz 200 100), visible := True]
where
updateGui st = do
rdl <- atomically $ readTVar trdl
atomically $ writeTVar trdl []
case rdl of
[] -> return()
dat : dl -> set st [text := (show dat)]
main :: IO()
main = startClient >>= start gui
因此,客戶端偵聽TCP連接上的更新,將它們添加到隊列中。每隔10ms,就會發起一個事件,其操作是檢查此隊列並在靜態文本小部件中顯示最新更新。
如果您有更好的解決方案,請告訴我!
從我可以告訴沒有任何理由貴公司不能在TVAR重試,並做這種異步(但是,是的,任何時候線程阻塞wx似乎中斷)。我也嘗試了反轉這個概念,並且將'st str [text:= str]'寫入TVar,然後讓'startClient'調用這個來更新GUI,但是這似乎無限地阻塞了'set'。 WX已經證明相當令人沮喪,所以我認爲我會堅持使用GTK。 – 2010-07-06 18:53:08
我發現在沒有忙等待一個解決方案: http://snipplr.com/view/17538/
然而,你可能會爲了避免與現有的ID衝突選擇更高的事件ID。
這裏是我的模塊http://code.haskell.org/alsa/gui/src/Common.hs一些代碼:
myEventId :: Int
myEventId = WXCore.wxID_HIGHEST+100
-- the custom event ID, avoid clash with Graphics.UI.WXCore.Types.varTopId
-- | the custom event is registered as a menu event
createMyEvent :: IO (WXCore.CommandEvent())
createMyEvent =
WXCore.commandEventCreate WXCore.wxEVT_COMMAND_MENU_SELECTED myEventId
registerMyEvent :: WXCore.EvtHandler a -> IO() -> IO()
registerMyEvent win io =
WXCore.evtHandlerOnMenuCommand win myEventId io
reactOnEvent, reactOnEventTimer ::
SndSeq.AllowInput mode =>
Int -> WX.Window a -> Sequencer mode ->
(Event.T -> IO()) ->
IO()
reactOnEvent _interval frame (Sequencer h _) action = do
mvar <- MVar.newEmptyMVar
void $ forkIO $ forever $ do
MVar.putMVar mvar =<< Event.input h
WXCore.evtHandlerAddPendingEvent frame =<< createMyEvent
registerMyEvent frame $
MVar.takeMVar mvar >>= action
-- naive implementation using a timer, requires Non-Blocking sequencer mode
reactOnEventTimer interval frame sequ action =
void $
WX.timer frame [
WX.interval := interval,
on command := getWaitingEvents sequ >>= mapM_ action]
的代碼顯示了兩種方式來處理這個問題:
reactOnEventTimer
不使用WX定時器忙等待。reactOnEvent
只有在事件實際到達時纔會激活。這是首選解決方案。
在我的例子中,我等待ALSA MIDI音序器消息。 Event.input調用等待下一個ALSA消息。 action
獲取Event.input的結果,即傳入的ALSA消息,但它在WX線程中運行。
歡迎來到StackOverflow。雖然這可能回答 問題,[這將是更可取的](http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers/8259 #8259)在這裏包括答案的基本部分,並提供供參考的鏈接。 – Chris 2012-09-26 07:33:06
- 1. 異步更新
- 2. 異步TaskUI更新
- 3. 更新UI異步?
- 4. 異步插入&更新異步插入&更新:NoSql和SQL
- 5. 更新DIV異步---更新評論
- 6. 異步更新數據庫
- 7. ASP.NET異步標籤更新
- 8. Peewee異步更新時
- 9. 異步更新vaadin組件
- 10. 更新ASP.NET面板異步
- 11. 用異步更新圖像
- 12. 異步更新WPF窗口
- 13. RestSharp異步API - 更新GUI
- 14. 異步更新控制
- 15. ListView SimpleCursorAdapter異步更新
- 16. 異步任務更新UI
- 17. ASIHTTPRequest異步更新uitableview
- 18. Spark用於異步更新。
- 19. 異步更新文本框
- 20. 異步更新ASP.NET圖表
- 21. 如何異步更新winform?
- 22. 異步進度欄更新
- 23. 異步更新面板_
- 24. UICollectionView異步更新大小
- 25. ListActivity的異步更新
- 26. 異步使用異步和等待更新Winforms中一個TreeView
- 27. 異步更新wpf UI從另一個線程異步
- 28. Xamarin.Forms ListView ItemsSource - 異步更新NullReferenceException
- 29. 自動完成UITextField異步更新UITableView
- 30. 使用WakefulIntentService管理異步GPS更新
你能否澄清你的問題。你究竟在尋找什麼?從單獨的進程通知Haskell進程的模型? – 2010-07-05 01:09:11
這裏是一個例子。在一個單獨的過程中,有一個計數器。每次計數器遞增時,它都會通過TCP向其他Haskell進程(客戶端)發送消息。客戶端管理一個顯示計數器值的gui(在WxHaskell中)。當客戶端收到更新時,我想更新顯示器上的計數器。 – Alex 2010-07-05 08:42:37
根據你的評論我發佈了一個答案。如果有的話,我的回答中有哪些概念與你的問題有關? Haskell線程(forkIO)?線程之間的通信(MVars,STM/TVars)?別的東西或不在我的答案? – 2010-07-05 18:45:46