多线程崩溃中的 sizeWithFont!

Posted

技术标签:

【中文标题】多线程崩溃中的 sizeWithFont!【英文标题】:sizeWithFont in MultiThread Crash! 【发布时间】:2011-04-01 11:16:21 【问题描述】:

sizeWithFont 在多线程中崩溃,这是调试信息:

1 0x00a0df8e in icu::RuleBasedBreakIterator::handleNext
2 0x00a0daff in icu::RuleBasedBreakIterator::next
3 0x00a0d174 in icu::RuleBasedBreakIterator::following
4 0x35879719 in WebCore::nextBreakablePosition
5 0x3587842a in -[NSString(WebStringDrawing) _web_drawInRect:withFont:ellipsis:alignment:lineSpacing:includeEmoji:measureOnly:]
6 0x35877da3 in -[NSString(WebStringDrawing) _web_sizeInRect:withFont:ellipsis:lineSpacing:]
7 0x3090d238 in -[NSString(UIStringDrawing) sizeWithFont:constrainedToSize:lineBreakMode:lineSpacing:]
8 0x3090cee3 in -[NSString(UIStringDrawing) sizeWithFont:constrainedToSize:lineBreakMode:]

现在我通过使用一个 NSLock 对象来解决这个错误,在使用这个函数之前我会锁定这个对象,然后解锁它

但我认为必须有更好的解决方案!

我发现这个错误只有在两个线程上这个函数的 NSString 对象都是多行文本时才会出现

【问题讨论】:

当然,我编辑了标签,但您确实需要更连贯地解释才能让任何人回答。 这些护目镜对这个问题无能为力!啊啊啊啊我的眼睛!!!!他们烧了!!! 【参考方案1】:

通常,您不应从单独的线程调用 UIKit 方法 [1]。如果您要锁定也没关系,这是行不通的。

当您使用多线程应用程序时,您需要确保任何涉及任何 UIKit 对象的代码都在主线程上执行。这是通过使用 performSelectorOnMainThread:withObject:waitUntilDone: 方法来实现的,该方法在主线程上调用给定的选择器:

http://developer.apple.com/iphone/library/documentation/cocoa/reference/foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelectorOnMainThread:withObject:waitUntilDone:

或者在 MonoTouch 中:foo.InvokeOnMainThread (delegate your_code_here );

[1] 在 ios 4.0 中,少数 API 的规则放宽了。

【讨论】:

包含 MonoTouch 版本对我有帮助,谢谢。【参考方案2】:

请格式化。

通过在对象周围放置随机锁来“解决”多线程问题绝不是正确的答案。永远不会。多线程需要对您的应用进行系统设计。

如果锁确实“解决”了问题,则显示您锁定的内容以及对评估情况的重要性。

更多症状会有所帮助。尤其是代码。您问题中的代码非常有用。

鉴于缺乏证据,我敢打赌,您正在改变一个线程上的字符串,同时试图获取另一个线程的大小。或者对象在一个线程上被释放,而另一个线程仍在使用它。或者您正在从非线程安全的辅助线程操作对象。

【讨论】:

不知道Cocoa对象,栈中引用的ICU对象肯定不能多线程这样使用。另一个答案似乎也支持这一点。我认为您需要弄清楚如何不同时从两个线程调用此对象。【参考方案3】:

我认为 performSelectorOnMainThread:withObject:waitUntilDone: 是正确的,

之前,我使用一个运算来计算文本大小, 并在主线程中使用waitUntilAllOperationsAreFinished等待操作返回, 但是如果我在操作中也使用了performSelectorOnMainThread:withObject:waitUntilDone,并且将waitUntilDone参数设置为Yes(因为我需要结果) 主线程会卡住

所以现在我删除 waitUntilAllOperationsAreFinished ,并使用异步对象来确保 直到前一个停止,操作才会开始

                    [md removeAllObjects];
                    [md setObject:subString forKey:@"text"];
                    [md setObject:[NSNumber numberWithInt:view_w ] forKey:@"width"];
                    [md setObject:[NSNumber numberWithInt:height_left + font_h ] forKey:@"height"];
                    [self  performSelectorOnMainThread:
                     @selector(calculateTextRegion:)
                                            withObject:md
                                         waitUntilDone:YES];
                    CGSize stringSize = textRegion;

【讨论】:

以上是关于多线程崩溃中的 sizeWithFont!的主要内容,如果未能解决你的问题,请参考以下文章

多线程环境中的 PersistentStore 协调器导致“未找到存储”崩溃

sizeWithFont:constrainedToSize:lineBreakMode: 在 iOS7 中已弃用

多线程,如果线程崩溃,应用程序会发生啥

多线程渲染仅在 iOS 13 上崩溃

在多线程崩溃的 MFC 中使用 Techart activeX

CoreData 多线程正在生成随机崩溃