如果我从UIView.StringSize
之类的某些异步代码中运行Task.ContinueWith
,那么它会以UIKitThreadAccessException
爆炸,因为该方法首先调用UIApplication.EnsureUIThread
(“转到声明“在MonoDevelop中;我不确定许可证允许我在这里发布它”。
Task.Factory.StartNew(() => {
// Blows up discretely...nothing written to application output.
// Also blows up for UIViews that exist only in code (not rendered).
SizeF textSize = someView.StringSize(someString, someFont, new SizeF(someView.Bounds.Width, float.MaxValue), UILineBreakMode.WordWrap);
Console.WriteLine(textSize);
});
如果我将此简化版本包装在InvokeOnMainThread
中,一切都很好,但我确实有时候想要在没有该调用的情况下测量一些文本。同样,我完全理解exception's purpose并且在以前在异步代码中深度调用某些内容时为我节省了一些麻烦,但在这种情况下,在这里使用EnsureUIThread
似乎是不必要的。如果我只是简单地将该调用重新作为NSString
类的命中,它将很乐意在UI线程之外运行。
Task.Factory.StartNew(() => {
// Outputs expected size data: "{Width=##, Height=##}".
using (NSString nssSomeString = new NSString(someString)) {
SizeF textSize = nssSomeString.StringSize(someFont, new SizeF(someView.Bounds.Width, float.MaxValue), UILineBreakMode.WordWrap);
Console.WriteLine(textSize);
}
});
UIView.StringSize
的代码看似大致相同的NSString
工作,并且似乎没有任何公开的UI线程导向。是否有一些我缺少的东西,需要从UI线程调用这个版本的方法?
我filed a bug with Xamarin只是为了看到他们的回应。听起来他们正在考虑将此方法标记为ThreadSafe
。
答案 0 :(得分:1)
这是因为您的UIView
正在从未创建的线程进行访问。由于您在后台线程中创建NSString
,因此您的第二个示例将正常工作并建议使用。 (虽然我认为您不应该尝试从后台线程访问someView.Bounds
)
我怀疑这也有用:
var bounds = someView.Bounds; //UI thread
Task.Factory.StartNew(() => {
// Outputs expected size data: "{Width=##, Height=##}".
using (UIView view = new UIView()) {
SizeF textSize = view.StringSize(someString, someFont, new SizeF(bounds.Width, float.MaxValue), UILineBreakMode.WordWrap);
Console.WriteLine(textSize);
}
});
但我会坚持使用NSString
:
var bounds = someView.Bounds; //UI thread
Task.Factory.StartNew(() => {
// Outputs expected size data: "{Width=##, Height=##}".
using (NSString nssSomeString = new NSString(someString)) {
SizeF textSize = nssSomeString.StringSize(someFont, new SizeF(bounds.Width, float.MaxValue), UILineBreakMode.WordWrap);
Console.WriteLine(textSize);
}
});
答案 1 :(得分:0)
StringSize
方法的UI限制确实是不必要的。 Xamarin已经fixed this for "v6.0.10+"。
我们已经认识到DrawString(drawInRect:* selectors)很好 其他线程。 StringSize是该功能的子集,因此它应该是安全的。 未来版本(6.0.10+)将标记为[ThreadSafe]。
在您对更新版本进行编码之前,NSString
版本可以正常运行。