Kristof
Kristof

Reputation: 445

Gtk# window movement freezes when multi-threaded

I'm currently trying to use multi-threaded Gtk# under Windows.

Everything works fine except for this little bug that makes the application unusable : you can't move or resize the app, because it freezes.

It looks like a potential bug in Gtk#.

Here's a sample that reproduces the issue : a simple window, a label and a button. The label and button are not necessary, but provide the proof that otherwise Gtk is performing normally. Whenever I move the windows, maximize it, it stalls.

using System;
using Gtk;

namespace FreezingWindow
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            if (GLib.Thread.Supported) {
                GLib.Thread.Init ();
            }

            Gdk.Threads.Init ();

            Gdk.Threads.Enter ();
            Application.Init ();
            Window win = new Window ("test");

            var box = new VBox ();

            var label = new Label ("Test");
            box.PackStart (label);

            var btn = new Button ("Test");
            btn.Clicked += delegate(object sender, EventArgs e) {
                label.Text = DateTime.Now.ToString();
            };
            box.PackStart (btn);

            win.Add (box);
            win.ShowAll ();
            Application.Run ();
            Gdk.Threads.Leave ();
        }
    }
}

Upvotes: 2

Views: 539

Answers (1)

CSmanic
CSmanic

Reputation: 78

Here's how I work with multi-threading + GUI changes. I completely avoid the threading methods you've utilized and stictly use the System.Threading namespace. It creates true multi-threaded applications with responsive GUI. (Also, I typically create a separate class that is strictly for the form and all of its methods.)

// Create the thread and tell it to execute the DoThreadStuff method.
Thread thread = new Thread(new ThreadStart(DoThreadStuff));
thread.Start();

Update the GUI by utilizing Application.Invoke.

private void DoThreadStuff()
{
    // Stuff that is processing on the separate thread.
    // Need to use Application.Invoke if updating the GUI from the thread.

    Application.Invoke(delegate {
        label.Text = string.Format("Did stuff at {0}", DateTime.Now);
    });
}

Another method I like to use is to create a generic method that accepts a method name that we need to execute under Application.Invoke.

private void InvokeMethod(System.Action methodName)
{
    Application.Invoke(delegate {
        methodName();
    });
}

Upvotes: 0

Related Questions