世事洞明皆学问,人情练达即文章。这篇文章主要讲述同步/阻止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();
});
}
推荐阅读
- 在VS 2017 xamarin android项目中没有击中断点
- 如何在Cordova中检索应用程序版本,应用程序名称,程序包名称,版本代码和版本号
- 5个最佳网页加载进度条javascript插件
- 5+最佳的jquery和javascript datepicker插件
- 5个最佳Cookie政策横幅javascript插件
- 5+最佳代码语法高亮javascript插件
- 5个人脸跟踪和识别相关的最佳javascript库
- 5+最佳免费图表JavaScript库
- 7个最佳语音命令和语音识别相关的javascript库