Application.Invoke不不需要更換(至少我使用的版本)。這是一種誤解。 Application.Inoke只是簡單地轉向,並將一個委託添加到GLib.Timeout中,超時設置爲0,並返回「false」,因此只能觸發一次。
我沒有去掉Application.Invoke,而是試圖找出爲什麼我的委託在使用Application.Invoke時沒有Appliation.Run或Application.Init。請記住,我已經開始了我自己的GLib.MainLoop。
事實證明,應用程序的靜態構造函數調用GLib.Thread.Init(),它基本上是一個時間炸彈。 GLib的文檔指出,當使用多線程時必須調用GLib.Thread.Init,並且如果GLib.Thread.Init調用了有史以來,它必須在調用任何其他GLib用法之前調用。
因此,在我正在使用的代碼中,我們添加了一個委託給GLOB.Timeout 後 Application.Init,但在Application.Run之前,以及對Application.Invoke的任何調用之前。這意味着我們是安全的,因爲Application.Init會調用Application的靜態構造函數,因此調用GLib.Thread.Init。這很好。但是,當我們刪除Application.Init並且首先調用Timeout.Add時,Thread.Init尚未被調用。這意味着如果我們稍後調用Thread.Init,線程,超時,委託等將會窒息。
果然,Application.Invoke或Application.Run會調用Application的靜態構造函數,然後調用GLib.Thread.Init。這導致了這個問題。
TLDR;長篇小說,請確保您在應用程序代碼中使用Timeout.Add之前調用應用程序的靜態構造函數。不要手動調用Glib.Thread.Init,因爲在Mono上調用它兩次會使應用程序崩潰。
這是正常的:
Application.Init();
Timeout.Add(0, delegate { return false; });
Application.Invoke(delegate { Console.WriteLine("Hey"); });
Application.Run();
這會毀了你的生活:
// Application.Init();
Timeout.Add(1000, delegate { return false; });
Application.Invoke(delegate { Console.WriteLine("Hey"); });
new MainLoop().Run();
//Application.Run();
但是,這是罰款:
// Application.Init();
Application.Invoke(delegate {});
Timeout.Add(1000, delegate { return false; });
Application.Invoke(delegate { Console.WriteLine("Hey"); });
new MainLoop().Run();
//Application.Run();
類調用這些所調用是假設它是異步激發它的事件,因爲它必須保持處理數據。同步調用它們會掛起主要的處理過程,導致數據丟失或數據中斷。基本上,該線程正在處理我們無法控制的硬件。 –
我在尋找什麼線程類來模擬/模擬Application.Invoke在幕後做些什麼。 –
Application.Invoke總是調用它在主GTK循環中找到的任何東西。如果你有一個硬件處理線程,那麼你需要做'添加到列表'的東西。 – IanNorton