sizeWithFont в MultiThread Crash! - PullRequest
       8

sizeWithFont в MultiThread Crash!

3 голосов
/ 20 августа 2010

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 для этой функции в обоих потоках представляет собой многострочный текст

Ответы [ 3 ]

4 голосов
/ 20 августа 2010

Как правило, вы не должны вызывать методы UIKit [1] из отдельного потока.Это не имеет значения, если вы берете блокировки, это не стартер.

Когда вы используете многопоточные приложения, вам нужно убедиться, что любой код, который касается любых объектов UIKit, выполняется в главном потоке.,Это достигается с помощью executeSelectorOnMainThread: 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 (делегат {ваш_код_ здесь});

[1] В iOS 4.0 правило смягчено для нескольких API.

4 голосов
/ 20 августа 2010
  • Форматирование, пожалуйста.

  • «Решение» многопоточной задачи путем размещения случайных блокировок вокруг объектов никогда не является правильным ответом. Никогда не. Многопоточность требует системного дизайна вашего приложения.

  • Если блокировка «устраняет» проблему, показывая, что вы заблокировали и как это важно для оценки ситуации.

  • Было бы полезно еще несколько симптомов. Кодекс, в частности. Код в ваших вопросах очень полезен.

Учитывая отсутствие доказательств, я бы держал пари, что вы мутируете строку в одном потоке, пытаясь получить размер в другом. Или объект освобождается в одном потоке, в то же время используя его в другом. Или вы управляете объектом из вторичного потока, который не является потокобезопасным.

0 голосов
/ 07 сентября 2010

Я думаю, что executeSelectorOnMainThread: withObject: waitUntilDone: правильно,

До этого я использую операцию для вычисления размера текста, и использую waitUntilAllOperationsAreFinished в главном потоке, чтобы дождаться ее возврата,
Но еслиЯ также использую executeSelectorOnMainThread: withObject: waitUntilDone в операции и устанавливаю для параметра waitUntilDone значение Да (поскольку мне нужен результат)
Основной поток будет зависать

Так что теперь я удаляю 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;
...