使用 System.Timers.Timer 设置 GtkSharp ComboBox 时出现段错误
Segfault when setting a GtkSharp ComboBox with a System.Timers.Timer
我在使用 System.Timers
中的 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);
的调用,您将按预期执行此操作。
段错误要么是 Mono 错误,要么是在 GTK 中错误使用线程的结果。请用这个小工具来判断是不是后者:https://github.com/slluis/gui-thread-check
我知道怎么做了。如果你正在处理多个线程,你需要将你的 GTK GUI 调用封装在一个委托中,并将其传递给 Gtk.Application.Invoke()
.
例如
Gtk.Application.Invoke(delegate {
comboBox1.AppendText("Option X");
});
这是安全和正确的方法。
我在使用 System.Timers
中的 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);
的调用,您将按预期执行此操作。
段错误要么是 Mono 错误,要么是在 GTK 中错误使用线程的结果。请用这个小工具来判断是不是后者:https://github.com/slluis/gui-thread-check
我知道怎么做了。如果你正在处理多个线程,你需要将你的 GTK GUI 调用封装在一个委托中,并将其传递给 Gtk.Application.Invoke()
.
例如
Gtk.Application.Invoke(delegate {
comboBox1.AppendText("Option X");
});
这是安全和正确的方法。