Multithreading Gtk#多线程时窗口移动冻结

Multithreading Gtk#多线程时窗口移动冻结,multithreading,gtk#,Multithreading,Gtk#,我目前正在尝试在Windows下使用多线程Gtk 除了这个使应用程序无法使用的小错误之外,一切正常:你不能移动或调整应用程序的大小,因为它会冻结 这看起来像是Gtk中的一个潜在错误 下面是一个重现问题的示例:一个简单的窗口、一个标签和一个按钮。标签和按钮不是必需的,但提供证明Gtk正常运行的证据。每当我移动窗户,最大化它,它就会停止 using System; using Gtk; namespace FreezingWindow { class MainClass {

我目前正在尝试在Windows下使用多线程Gtk

除了这个使应用程序无法使用的小错误之外,一切正常:你不能移动或调整应用程序的大小,因为它会冻结

这看起来像是Gtk中的一个潜在错误

下面是一个重现问题的示例:一个简单的窗口、一个标签和一个按钮。标签和按钮不是必需的,但提供证明Gtk正常运行的证据。每当我移动窗户,最大化它,它就会停止

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 ();
        }
    }
}

下面是我如何处理多线程+GUI更改的方法。我完全避免使用您使用的线程方法,并坚持使用System.threading命名空间。它使用响应性GUI创建真正的多线程应用程序。(另外,我通常创建一个单独的类,该类严格适用于表单及其所有方法。)

利用Application.Invoke更新GUI

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);
    });
}
private void InvokeMethod(System.Action methodName)
{
    Application.Invoke(delegate {
        methodName();
    });
}
我喜欢使用的另一个方法是创建一个通用方法,该方法接受我们需要在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);
    });
}
private void InvokeMethod(System.Action methodName)
{
    Application.Invoke(delegate {
        methodName();
    });
}

谢谢你的信息。然而,我想使用多线程的主要原因是为了加速Cairo绘图,这是用这种方法无法实现的。我个人不知道有什么方法可以真正做你想做的事。也许有办法,但我不知道。我认为所有核心内的重画都发生在同一个线程上,或者疯狂开始发生。再说一次,我可能大错特错,但这是我的理解。我很想知道是否有一些方法可以做到这一点,而不必分叉GTK,也不必在源代码中创建自己的多线程绘图版本。到目前为止,我发现GTK 2基本上应该是多线程的,但如果有我所描述的bug,它是没有用的。然而,对于GTK3,他们似乎已经完全消除了多线程意识,因此我们别无选择,只能使用您描述的方法。。。