如何从分叉线程安全地使用WebKitGTK?

时间:2014-07-27 01:37:50

标签: multithreading haskell gtk webkitgtk

我试图使用GTK3和WebKit在Haskell中创建一个简单的应用程序。此代码创建并显示一个内部包含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 个答案:

答案 0 :(得分:1)

如果它像python一样(我不知道haskell),你应该将gtk main loop保留在main thread

在您的第二个主题调用g_idle_add中,使用回调功能对gtk进行更改,transport data between使用second threadgtk进行更改。你应该在gtk main之前开始你的非主线程,这样它就不会被阻止。

我确定haskell中有g_idle_add的绑定。还有g_timeout_add也适用于此。

这一切都与gtk不是线程安全有关。