# Ensuring Gtk.jl responsivity

**URL:** <https://discourse.julialang.org/t/ensuring-gtk-jl-responsivity/40710>\
**Category:** General Usage\
**Tags:** gtk\
**Created:** [June 4, 2020, 7:13am UTC](https://discourse.julialang.org/t/ensuring-gtk-jl-responsivity/40710 "2020-06-04T07:13:42Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![xor0110](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xor0110/32/7926_2.png) [@xor0110](https://discourse.julialang.org/u/xor0110)\
**Post date:** [June 4, 2020, 7:13am UTC](https://discourse.julialang.org/t/ensuring-gtk-jl-responsivity/40710/1 "2020-06-04T07:13:42Z")

</div>

I’m writing a Gtk.jl application, and it’s easy to see that any time some time-consuming activity happens, such as running a long computation, this interferes with the UI responsivity. In especial, even updating a label with a message such as “Please wait while I perform your long computation” may not work, what can be quite annoying.

I imagine this must be due to something like the computations running in the main thread and blocking Gtk(.jl) from doing whatever it needs. What is a good way to move these computations away to a different thread? Or would tasks help? And maybe a more philosophical question: how to structure this program with computations running in parallel so that you have the same imperative step-by-step execution from the original blocking application?

Example app. You probably never get to see the first message in the label, only the final one with the computation result.

```julia
using Gtk
using LinearAlgebra

b = Gtk.Button("oi")
ll = Gtk.Label("output")
hb = Gtk.Box(:v)
w = Gtk.Window("x")

push!(hb,b)
push!(hb,ll)
push!(w, hb)

function calcpi(niter)
    acc = 0
    for n in 1:niter
        if norm(rand(2)) < 1.0
            acc += 1
        end
    end
    return 4*acc/niter
end

signal_connect(b, "clicked") do widget
    @info "Button clicked 1"
    GAccessor.text(ll,"Running your long calculation...")

    # niter = 100000000
    niter = 10000000
    # niter = 1000000
    mypi = calcpi(niter)
    @info mypi
    GAccessor.text(ll,"done, mypy=$mypi")
end

showall(w)

```

---

<div class="post-metadata">

**Author:** ![xor0110](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xor0110/32/7926_2.png) [@xor0110](https://discourse.julialang.org/u/xor0110)\
**Post date:** [June 4, 2020, 8:01pm UTC](https://discourse.julialang.org/t/ensuring-gtk-jl-responsivity/40710/2 "2020-06-04T20:01:28Z")

</div>

Some extra info: I have tried to put the calculation in a separate thread using `@spawn`, and even wrote a little polling loop that prints to the console while waiting for the calculation to stop. Still the UI freezes, not only the label does not get updated, the whole UI really freezes. Should I really actually finish the callback before the UI can be updated again?

---

<div class="post-metadata">

**Author:** ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)\
**Post date:** [June 5, 2020, 12:23pm UTC](https://discourse.julialang.org/t/ensuring-gtk-jl-responsivity/40710/3 "2020-06-05T12:23:44Z")

</div>

Hey @xor0110,  
this has been a long term issue, but with Julia 1.3 and its threading capabilities it actually works. Have a look at this example.

> [@Threading 1.3: Success Story](https://discourse.julialang.org/t/threading-1-3-success-story/27111/2):
>
> To answer the question myself, the following runs the UI updating code on the main thread again: using Gtk.ShortNames b = Box(:v) win = Window(b,"test") button = Button("do work") push!(b,button) pb = ProgressBar() push!(b,pb) Gtk.showall(win) function doWork() N = 20 for k=1:N Gtk.GLib.g\_idle\_add(nothing) do user\_data set\_gtk\_property!(pb,:fraction,(k-1)/(N-1) ) Cint(false) end sum(collect(1:100000000)) # some heavy work end end signal\_connect(button, "clic…

The point is to spawn the thread and put all UI code into an idle\_add.

One missing piece in that code is to spawn the thread at a different thread than the master thread. There is some package exactly for that purpose, but I have not tried it yet (you need to search in the forum, I do not remember the name).

---

<div class="post-metadata">

**Author:** ![xor0110](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xor0110/32/7926_2.png) [@xor0110](https://discourse.julialang.org/u/xor0110)\
**Post date:** [June 6, 2020, 11:35am UTC](https://discourse.julialang.org/t/ensuring-gtk-jl-responsivity/40710/4 "2020-06-06T11:35:58Z")

</div>

Thanks, it’s good to hear from more people writing this kind of application. I think there’s a huge potential to be explored in Julia writing guis with libraries such a Gtk, which seems to be the most usable right now.

I got my application to do what I wanted, although I’m not entirely sure how it relates to you answer. What I noticed is you just have to make sure all your UI updates happen at the end of a callback call (or worker thread), and then as soon as that function is over the UI will be able to update. My scenario is different since I’m not really interested in interactive updates together with the calculations, which is of course a more interesting case.

Here’s my current example app. It requires `@spawn`, although I’m not even sure having actual separate threads is really required. A task taking over would work in this case since my problem is just that updates from before the calculation don’t even happen. It doesn’t really matter for me if it all gets blocked.

```julia
using Gtk
using LinearAlgebra
import Base.Threads.@spawn

b = Gtk.Button("oi")
ll = Gtk.Label("output")
hb = Gtk.Box(:v)
w = Gtk.Window("x")

push!(hb,b)
push!(hb,ll)
push!(w, hb)
state = :startcomp

signal_connect(b, "clicked") do widget
    global state
    if state == :startcomp
        @info "Button clicked 1"
        GAccessor.text(ll,"Running your long calculation...")
        state = :computing
        @spawn dolongcomp()
    end
end

function dolongcomp()
    global state

    niter = 100000000
    mypi = calcpi(niter)

    @info mypi
    GAccessor.text(ll,"done, mypy=$mypi")
    state = :startcomp
end

function calcpi(niter)
    acc = 0
    for n in 1:niter
        if norm(rand(2)) < 1.0
            acc += 1
        end
    end
    return 4*acc/niter
end

showall(w)

```

I had some great experience some time ago writing a Scala + Akka GUI where one actor runs in the main thread, and is the only one allowed to perform UI actions. Computations are performed by other actors which run in a separate thread pool, and communicate with the GUI actor. I would love to figure out how to do something like that in Julia. Tasks and Channels might provide enough capability for it, although I’m not sure how to even start. My example app right now is not so great because we have some logic tied straight to a button callback, and the other UI update should be triggered by some kind of custom signal. I don’t know if Gtk allows you to implement this.

---

<div class="post-metadata">

**Author:** ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)\
**Post date:** [June 6, 2020, 8:25pm UTC](https://discourse.julialang.org/t/ensuring-gtk-jl-responsivity/40710/5 "2020-06-06T20:25:26Z")

</div>

I have implemented something similar. It uses a global struct where the computation thread updates the state and a UI thread/task updates the UI. I have been using a `Timer` for the UI task but you can also use `@spawn` with a thread and a sleep. But thinking longer about it, it would even better to use `g_timeout_add` :

> <https://github.com/JuliaGraphics/Gtk.jl/blob/master/test/glib.jl#L37>

This is a function that regularly calls a callback until the callback returns false.

For the global variable you should use `const Ref` to get no performance penalty.

---

<div class="post-metadata">

**Author:** ![xor0110](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xor0110/32/7926_2.png) [@xor0110](https://discourse.julialang.org/u/xor0110)\
**Post date:** [June 7, 2020, 9:12am UTC](https://discourse.julialang.org/t/ensuring-gtk-jl-responsivity/40710/6 "2020-06-07T09:12:34Z")

</div>

I tried replacing my `@spawn` call with `g_idle_add` and again I got the behavior where the UI doesn’t get updated before the computation starts.

---

<div class="post-metadata">

**Author:** ![tknopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tknopp/32/3569_2.png) [@tknopp](https://discourse.julialang.org/u/tknopp)\
**Post date:** [June 7, 2020, 2:13pm UTC](https://discourse.julialang.org/t/ensuring-gtk-jl-responsivity/40710/7 "2020-06-07T14:13:53Z")

</div>

That is clear. My suggestion was if you want to split the computation thread from the UI thread. g\_idle\_add should only get UI update to do. No computation in that callback.

---

<div class="post-metadata">

**Author:** ![xor0110](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xor0110/32/7926_2.png) [@xor0110](https://discourse.julialang.org/u/xor0110)\
**Post date:** [June 7, 2020, 5:03pm UTC](https://discourse.julialang.org/t/ensuring-gtk-jl-responsivity/40710/8 "2020-06-07T17:03:54Z")

</div>

OK, I think I get it then: to make sure something that needs to be run in the main thread goes there, we can use `g_idle_add` from whatever threads, is that it? One last question I would have, though is what actually really requires this. I’m not sure this is really the case from the `GAccessor.text` in my example, for instance.

---

<div class="post-metadata">

**Author:** ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)\
**Post date:** [June 9, 2020, 10:02am UTC](https://discourse.julialang.org/t/ensuring-gtk-jl-responsivity/40710/9 "2020-06-09T10:02:16Z")

</div>

> [@xor0110](#):
>
> OK, I think I get it then: to make sure something that needs to be run in the main thread goes there, we can use `g_idle_add` from whatever threads, is that it?

yes, its not safe to call drawing code from arbitrary code and `idle_add` is the way to make an asynchron drawing operation. `timeout_add` is similar but allows repeated redrawing, which is useful, if you have a computation going on and want to monitor the computation with you UI.

> [@xor0110](#):
>
> One last question I would have, though is what actually really requires this. I’m not sure this is really the case from the `GAccessor.text` in my example, for instance.

I actually do not know, what operations are allowed and which not. You can google a little bit around what information you find on that. My understanding is that one should not change UI from a non-UI thread. And actually it makes, from my perspective, the code also cleaner if one uses an `idle_add` to trigger an asynchron UI update.
