2014-07-27 11 views
8

Tôi đang cố gắng tạo một ứng dụng đơn giản trong Haskell bằng GTK3 và WebKit. Mã này tạo ra và hiển thị một cửa sổ có chứa một bên trong WebView, hiển thị một số ngẫu nhiên mỗi khi một phím được nhấn.Tôi có thể sử dụng WebKitGTK một cách an toàn từ một sợi chỉ được chia nhỏ như thế nào?

import   Control.Monad.Trans (lift) 
import   Control.Concurrent (forkOS) 
import   System.Random (randomIO) 
import   Graphics.UI.Gtk     -- gtk3 
import   Graphics.UI.Gtk.WebKit.WebView -- webkitgtk3 


main = forkOS $ do 

    -- Init GTK. 
    initGUI 

    -- Create a window which would finish the GTK loop 
    -- after being closed. 
    window <- windowNew 
    window `after` objectDestroy $ 
    mainQuit 

    -- Create a WebView inside. 
    webView <- webViewNew 
    set window [containerChild := webView] 

    -- Make the WebView display a random number on key press. 
    webView `on` keyReleaseEvent $ lift $ do 
    x <- randomIO :: IO Int 
    webViewLoadString webView (show x) Nothing Nothing "" 
    return True 

    -- Run GTK. 
    widgetShowAll window 
    mainGUI 

Khi tôi chạy nó trong GHCi (7.8.3), nó hoạt động tốt. Tuy nhiên, khi tôi chạy nó một lần nữa mà không bỏ GHCi, các WebView không bao giờ hiển thị bất cứ điều gì - chỉ là khu vực màu trắng đơn giản. Điều này là khó chịu, như tôi muốn tinker với mã trong GHCi.

Tất nhiên, mọi thứ hoạt động tốt nếu tôi không sử dụng forkOS và chạy toàn bộ nội dung trong chuỗi chính. Lý do cho giới hạn này là gì (tôi nghĩ rằng tất cả các chức năng GTK được coi là "chính" thread là một trong đó initGUI được gọi), và nó có thể được khắc phục bằng cách nào đó?

+0

Bạn có thể cần chạy một cách rõ ràng trong chuỗi bị ràng buộc bằng 'Control.Concurrent.runInBoundThread'. – vivian

+0

@vivian: bạn có thể mở rộng trên đó không? Tôi đã nghĩ về điều này, nhưng thêm 'runInBoundThread' ngay trước hoặc sau khi' forkOS' không giúp đỡ, và thêm 'print = << isCurrentThreadBound' cho thấy rằng luồng đó đã bị chặn. – Artyom

+0

Ứng dụng có hoạt động như mong đợi bên ngoài GHCi không? Có lẽ một số vòng lặp sự kiện đang bị dừng và không khởi động lại khi bạn chạy nó hai lần trong một quá trình duy nhất. –

Trả lời

1

Nếu nó hoạt động như python (Tôi không biết haskell), bạn nên giữ gtk main loop trong main thread.

Trong cuộc gọi chủ đề thứ hai của bạn g_idle_add với gọi lại để thực hiện thay đổi với gtk và transport data betweensecond threadgtk của bạn. Bạn nên bắt đầu chuỗi không chính của mình trước gtk main để nó không bị chặn.

Tôi chắc chắn có một ràng buộc là g_idle_add trong haskell. Ngoài ra còn có g_timeout_add cũng hoạt động cho điều này.

Tất cả điều này có liên quan đến gtk không phải là chủ đề an toàn.

Các vấn đề liên quan