使用System.Timers.Timer设置GtkSharp ComboBox时的Segfault

时间:2018-02-18 02:47:30

标签: c# timer gtk gtk#

我对Timer中的System.Timers对象有一点问题,并使用它在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代码,并在SetCB(null, null);之前添加了对Application.Run();的通话,您将会看到此功能符合预期。

2 个答案:

答案 0 :(得分:1)

段错误是Mono错误,或者是GTK中错误使用线程的结果。请使用这个小工具来确定它是否是后者:https://github.com/slluis/gui-thread-check

答案 1 :(得分:1)

我想出了如何做到这一点。如果您正在使用多个线程,则需要将GTK GUI调用包含在委托中,并将其传递给 var trianguloGeometry = new THREE.Geometry(); trianguloGeometry.vertices.push(new THREE.Vector3(0,0,0)); trianguloGeometry.vertices.push(new THREE.Vector3(0,50,0)); trianguloGeometry.vertices.push(new THREE.Vector3(50,0,0)); trianguloGeometry.vertices.push(new THREE.Vector3(0,0,0)); trianguloGeometry.vertices.push(new THREE.Vector3(0,50,0)); trianguloGeometry.vertices.push(new THREE.Vector3(-50,0,0)); trianguloGeometry.faces.push(new THREE.Face3(0,1,2)); trianguloGeometry.faces.push(new THREE.Face3(3,4,5)); trianguloGeometry.computeFaceNormals(); trianguloGeometry.computeFlatVertexNormals (); var triangulo = new THREE.Mesh( trianguloGeometry, new THREE.MeshLambertMaterial({ color:'red', side:THREE.DoubleSide, vertexColors:THREE.FaceColors }), ); scene.add(triangulo); triangulo.castShadow = true;

e.g。

Gtk.Application.Invoke()

这是安全的&amp;正确的方法。

相关问题