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.
Итак, в коде, с которым я работал, мы добавили делегата в GLib.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;
Короче говоря, убедитесь, что вы вызываете статический конструктор Application перед использованием 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();