Reputation: 445
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
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