Как я могу безопасно использовать WebKitGTK из разветвленной ветки?

Я пытаюсь сделать простое приложение на Haskell, используя GTK3 и WebKit. Этот код создает и показывает окно, содержащее WebView внутри, которое отображает случайное число при каждом нажатии клавиши.

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

Когда я запускаю его в GHCi (7.8.3), он работает нормально. Однако, когда я запускаю его снова, не выходя из GHCi, WebView никогда ничего не показывает - просто белая область. Это расстраивает, так как мне нравится возиться с кодом в GHCi.

Конечно, все работает отлично, если я не использую forkOS и запустить все это в главном потоке. В чем причина этого ограничения (я думал, что все функции GTK рассматривали "основной" поток как тот, в котором initGUI назывался), и можно ли это как-то побороть?

1 ответ

Если это работает как python(я не знаю haskell), вы должны сохранить gtk main loop в main thread,

В вашем втором потоке вызовите g_idle_add с обратным вызовом, чтобы внести изменения с помощью gtk, и transport data between ваш second thread, а также gtk, Вы должны начать свой неосновной поток до gtk main так что это не заблокировано.

Я уверен, что есть обязательство g_idle_add в хаскеле. Существует также g_timeout_add, который работает для этого тоже.

Это все связано с тем, что gtk не является потокобезопасным.

Другие вопросы по тегам