我正在尝试使用C#,Linux上的单声道/ GTK#和Windows上的.NET / GTK#创建跨平台C#应用程序,但是在两个平台下启动顺序似乎需要略有不同:
在Linux下:
public static void Main (string[] args)
{
Gdk.Threads.Init ();
// etc...
在Windows下:
public static void Main (string[] args)
{
Glib.Thread.Init ();
Gdk.Threads.Init ();
// etc...
两者都要求以这种方式完成:Windows抱怨g_thread_init()没有使用linux代码调用,并且linux抱怨已经使用Windows代码调用它。除此之外,这一切都非常有效。
我对“解决方案”的第一次尝试看起来像是:
public static void Main (string[] args)
{
try {
Gdk.Threads.Init ();
} catch (Exception) {
GLib.Thread.Init ();
Gdk.Threads.Init ();
}
// etc...
但即便是这种凌乱的解决方案也行不通;错误来自GTK +,非托管代码,因此无法捕获。有没有人对问题的原因有什么好主意,以及如何解决它?或者,如果不这样做,就如何检测应该在运行时调用哪一个有明智的想法?
答案 0 :(得分:8)
Win32上的Gtk +不能正确支持线程。您需要从与调用Gtk.Main()相同的线程执行所有GUI调用。
它实际上并不像听起来那么糟糕。有一个技巧可以用来将函数分派给主线程。只需从任何线程使用GLib.Idle.Add(),该函数将在主循环运行的同一个线程中立即调用。只需记住在空闲处理程序函数中返回false,否则它将继续运行。
如果你遵循并使用上述技巧,你根本不需要调用Gdk.Threads.Init()。
答案 1 :(得分:2)
我不确定这是否适用于Mono,但您可以使用Environment类来确定运行该程序的操作系统。
public static void Main (string[] args)
{
PlatformID platform = Environment.OSVersion.Platform;
if (platform == PlatformID.Win32NT ||
platform == PlatformID.Win32S ||
platform == PlatformID.Win32Windows)
Glib.Thread.Init();
else if (platform != PlatformID.Unix)
throw new NotSupportedException("The program is not supported on this platform");
Gdk.Threads.Init();
// etc...
PlatformID枚举不仅仅包含Windows和Unix,因此您应该检查其他值。
答案 2 :(得分:1)
实际上,这可能是GDK的C#绑定或您的GDK版本中的错误。根据{{1}}的文档必须首先调用,GTK#文档说的相同:
必须在gdk\_threads\_init(), g\_thread\_init()
之前调用{p>GLib.Thread.Init()
。
在我的Linux机器上(使用GDK 2.14.4),在没有调用Gdk.Threads.Init()
的情况下调用gdk\_threads\_init()
的C程序会输出错误消息并以错误终止。您是否确保在Linux和Windows上都拥有相同的GDK版本,并且Linux上的版本(如果它与Windows版本不同)也需要调用g\_thread\_init()
,或者它是否已经是两个版本之间发生了变化。最后,检查此程序是否以错误终止:
g\_thread\_init()
用#include <gdk/gdk.h>
int main(int argc, char **argv) {
gdk_threads_init();
return 0;
}
编译
(假设您已将其保存为test.c。)
如果该程序因错误而终止,则表明您的GDK#库中存在错误 如果没有,那就是你的GDK版本中的一个错误。
答案 3 :(得分:0)
嗯,您是否尝试使用[STAThread]属性装饰Main方法?
e.g。
#if !Mono //or whatever
[STAThread]
#endif
public static void Main (string[] args)
{
Gdk.Threads.Init ();
...
}
如果没有你可以像这样使用条件编译......
public static void Main (string[] args)
{
Gdk.Threads.Init ();
#if !Mono //or whatever
Gdk.Threads.Init ();
#endif
...
}