【问题标题】:Segfault when setting a GtkSharp ComboBox with a System.Timers.Timer使用 System.Timers.Timer 设置 GtkSharp ComboBox 时出现段错误
【发布时间】:2018-02-18 02:47:29
【问题描述】:

我对@9​​87654322@ 中的Timer 对象有一点问题,并使用它在 GTK 的 C# 绑定中设置 ComboBox 的选项;我遇到了段错误,我认为这是因为当Timer 调用其中一个附加的Elapsed 回调时,它在线程池中执行。这是问题的一些示例代码:

combobox1 是在 MonoDevelop 中使用 GUI 设计器添加的 Gtk ComboBox,MainWindow.cs

using System;
using System.Timers;
using System.Collections.Generic;
using Gtk;

public partial class MainWindow: Gtk.Window
{
    List<string> cbOptions = new List<string>();

    public MainWindow()
        : base(Gtk.WindowType.Toplevel)
    {
        Build();
        combobox1.Sensitive = false;
    }

    protected void OnDeleteEvent(object sender, DeleteEventArgs a)
    {
        Application.Quit();
        a.RetVal = true;
    }

    public void SetOptions(List<string> options, string initial)
    {
        // Clear & repopulate
        if (options?.Count > 0)
        {
            // Clear
            for (int i = 0; i < cbOptions.Count; i++)
                combobox1.RemoveText(0);

            // Set
            foreach (string opt in options)
                combobox1.AppendText(opt);

            // Set the default
            combobox1.Active = options.IndexOf(initial);
            combobox1.Sensitive = true;
            cbOptions = options;
        }   
        else
            combobox1.Sensitive = false;
    }   
}

Program.cs:

using System;
using System.Timers;
using System.Collections.Generic;
using Gtk;

namespace ComboBoxTest
{
    class MainClass
    {
        static MainWindow win;

        public static void Main(string[] args)
        {
            Application.Init();
            win = new MainWindow();
            win.Show();

            Timer t = new Timer(2000.0);
            t.Elapsed += SetCB;
            t.Start();

            Application.Run();
        }

        public static void SetCB(object sender, ElapsedEventArgs args)
        {
            List<string> options = new List<string>();
            for (int i = 1; i <= 25; i++)
                options.Add(string.Format("{0} 000 000 000", i));

            Random r = new Random();
            win.SetOptions(options, string.Format("{0} 000 000 000", r.Next(1, 25)));
        }
    }
}

是否有某种 GUI 线程可以确保回调正在运行,所以我不会遇到这个问题?如果您删除 Timer 代码并在 Application.Run(); 之前添加对 SetCB(null, null); 的调用,您将看到它按预期执行。

【问题讨论】:

    标签: c# timer gtk gtk#


    【解决方案1】:

    段错误要么是 Mono 错误,要么是在 GTK 中错误地使用线程的结果。请用这个小工具来判断是不是后者:https://github.com/slluis/gui-thread-check

    【讨论】:

    • 整洁的工具。有时间我会试试的。我弄清楚了真正的解决方案是什么并发布了一个答案。
    【解决方案2】:

    我想出了如何做到这一点。如果您在处理多个线程,则需要将您的 GTK GUI 调用封装在一个委托中,并将其传递给 Gtk.Application.Invoke()

    例如

    Gtk.Application.Invoke(delegate {
        comboBox1.AppendText("Option X");
    });
    

    这是安全正确的做法。

    【讨论】:

    • 是的,这正是 gui-thread-check 可以提供帮助的地方
    猜你喜欢
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 2015-03-24
    • 2018-02-25
    • 2014-12-07
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多