同步/阻止Application.Invoke()for GTK#

世事洞明皆学问,人情练达即文章。这篇文章主要讲述同步/阻止Application.Invoke()for GTK#相关的知识,希望能为你提供帮助。
不幸的是,Application.Invoke()是异步的:

private string ThreadFunction(int i) { string result = null; Gtk.Application.Invoke(delegate { OutputStringToUserInterface("i = " + i.ToString()); result = GetStringFromUserInterface(); }); return result; }

这意味着在这个例子中ThreadFunction()在调用Application.Invoke()之后立即进行,导致result字符串可能未定义的状态。 - 通常ThreadFunction()将更快并将返回旧值(即null)。

这是使用ManualResetEvent使Application.Invoke()同步的变通方法:
private string ThreadFunction(int i) { string result = null; using (var ev = new ManualResetEvent(false)) { Gtk.Application.Invoke(delegate { OutputStringToUserInterface("i = " + i.ToString()); result = GetStringFromUserInterface(); ev.Set(); }); ev.WaitOne(); }return result; }

这样,ThreadFunction()等到Application.Invoke()返回,就像使用WinForms Control.Invoke()一样。
编辑:更好的示例代码
EDIT2:添加缺少的using
现在我的问题是:有更好的解决方案吗?
答案嗯,是的,没有理由等待委托执行以获得正确的返回值。固定:
int result = i + 1;

让OutputStringToUserInterface()以异步方式执行是可以的,假设您不经常调用ThreadFunction(),因为它会使请求充满UI线程。
如果你的真实代码实际上依赖于必须在UI线程上运行的函数的返回值,那么不,你不能让它更快。显然,这是你真正想要避免的事情。
另一答案【同步/阻止Application.Invoke()for GTK#】您可以将当前代码封装到通用包装器中:
public static void GuiInvoke(Action action) { var waitHandle = new ManualResetEventSlim(); Gtk.Application.Invoke( (s,a) => { action(); waitHandle.Set(); }); waitHandle.Wait(); }public static void BeginGuiInvoke(Action action) { Gtk.Application.Invoke( (s,a) => {action(); }); }


    推荐阅读