不幸的是,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()就会像使用WinForms Control.Invoke()一样,等待Application.Invoke()返回。
编辑:更好的示例代码
EDIT2:添加缺失using
现在我的问题是:有更好的解决方案吗?
发布于 2010-02-06 14:10:39
是的,没有理由等待委托执行才能得到正确的返回值。修正:
int result = i + 1;让OutputStringToUserInterface()异步执行是可以的,前提是您不经常调用ThreadFunction(),因为它会让UI线程充满请求。
如果您的真正代码实际上依赖于必须在UI线程上运行的函数的返回值,那么,不行,您不能使它更快。很明显,这是你真正想要避免的。
发布于 2014-12-24 16:58:28
可以将当前代码封装到通用包装器中:
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();});
}https://stackoverflow.com/questions/2213243
复制相似问题