3

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 オブジェクトを使用してエラーを解決します。この関数を使用する前に、このオブジェクトをロックし、その後ロックを解除します

しかし、もっと良い解決策があるに違いないと思います!

このエラーは、2 つのスレッドの両方でこの関数の NSString オブジェクトが複数行のテキストである場合にのみ発生することがわかりました

4

3 に答える 3

4
  • フォーマットしてください。

  • オブジェクトの周りにランダムなロックを配置してマルチスレッドの問題を「解決」することは、決して正しい答えではありません。決して。マルチスレッドには、アプリケーションの体系的な設計が必要です。

  • ロックが問題を「修正」する場合は、ロックしたものとその方法を示して、状況を評価することが重要です。

  • いくつかのより多くの症状が役立ちます。特にコード。質問のコードは非常に便利です。

証拠がないことを考えると、別のスレッドでサイズを取得しようとしているときに、あるスレッドで文字列を変更していると思います。または、別のスレッドを使用している間に、オブジェクトが 1 つのスレッドで解放されています。または、スレッド セーフではないセカンダリ スレッドからオブジェクトを操作しています。

于 2010-08-20T03:58:37.803 に答える
4

原則として、別のスレッドから 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 についてルールが緩和されています。

于 2010-08-20T04:10:50.250 に答える
0

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;
于 2010-09-07T07:40:00.750 に答える