sizeWithFont in MultiThread Crash!
-
30-09-2019 - |
Domanda
sizeWithFont si è schiantato in multithread, questo è l'informazioni di debug:
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:]
ora risolvere l'errore utilizzando un oggetto NSLock, prima di usare questa funzione io bloccare questo oggetto, e dopo che lo sblocco
ma credo che ci deve essere una soluzione più meglio!
e ho trovato questo errore apparso solo quando l'oggetto NSString per questa funzione su entrambi due fili sono linee multiple di testo
Soluzione
Come regola generale, non si dovrebbe invocare metodi UIKit [1] da un thread separato. Non importa se sta assumendo serrature, questo è un non-starter.
Quando si utilizza applicazioni multi-threaded, è necessario fare in modo che tutto il codice che tocca ogni UIKit oggetti eseguito sul thread principale. Ciò si ottiene utilizzando il performSelectorOnMainThread: withObject: waitUntilDone: metodo che richiama la proposta selettore sul thread principale:
O in MonoTouch: foo.InvokeOnMainThread (delegato {your_code_here});
[1] Con iOS 4.0 la regola è rilassato per una manciata di API.
Altri suggerimenti
-
Formattazione, per favore.
-
"Soluzione" un problema multi-threaded, ponendo blocchi casuali intorno agli oggetti non è mai la risposta giusta. Non mai. Multi-threading richiede una progettazione sistemica della vostra applicazione.
-
Se un blocco non "fissare" il problema, mostrando ciò che è stato bloccato e come è fondamentale per valutare la situazione.
-
Alcuni altri sintomi sarebbe utile. Codice, in particolare. Codice nel tuo domande è molto utile.
Data la mancanza di prove, scommetto che il vostro stanno mutando una stringa su un thread durante il tentativo di afferrare la dimensione su un altro. O l'oggetto viene rilasciato su un thread pur utilizzando un altro. Oppure si stanno manipolando un oggetto da un thread secondario che non è thread-safe.
Credo performSelectorOnMainThread: withObject: waitUntilDone: è corretto,
Prima, io uso un'operazione per calcolare la dimensione del testo,
E l'uso waitUntilAllOperationsAreFinished nel thread principale per attendere il ritorno del funzionamento,
Ma se io uso anche performSelectorOnMainThread: withObject: waitUntilDone nel funzionamento, e impostare il parametro waitUntilDone su Yes (Perché ho bisogno del risultato)
Il filo conduttore sarà stucked
Così ora tolgo waitUntilAllOperationsAreFinished, e utilizzare un oggetto asincrono per garantire l'operazione non comincerà fino a quando il precedente fermato
[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;