2017-03-15 2 views
0

-app hat serielle Warteschlange für NSURLConnection läuftWenn ich Realm hinzufügen dann sperrt sie CFRunLoopRun und meine Warteschlange für NSURLConnection

-app zu connectionDidFinishLoading Ereignis abonniert

-App macht einfach ‚Ping‘ an Ort und läuft CFRunLoopRun in der Warteschlange Ereignisse aktivieren

-app schließt Verbindung nach connectionDidFinishLoading Ereignis empfängt, auf CFRunLoopRun Ausfahrt protokollieren wir es und nach dem Austritt aus der Warteschlange Aufgabe noch eine weitere Aufgabe wird Schlitz erhalten für die Ausführung

-aber wenn wir Realm hinzufügen dann CFRunLoopRun läuft auf unbestimmte Zeit und jetzt unsere Warteschlange

gesperrt ist

Ich öffnete Ticket https://github.com/realm/realm-cocoa/issues/4737 auch

#import "Realm/Realm.h" 

@interface ViewController() <NSURLConnectionDataDelegate> 
@end 

@implementation ViewController { 
    dispatch_queue_t my_queue; 
    NSURLConnection *_connection; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    my_queue = dispatch_queue_create("my queue", NULL); 

    dispatch_async(my_queue, ^{ 

    [RLMRealm defaultRealm];  // (1) // comment to make it running 
    NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://google.com"]]; 
    _connection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES]; 
    CFRunLoopRun();    // (2) infinite loop inside ios so (3) and (4) as result never been called 
    NSLog(@"done");    // (3) 

    }); 

} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    dispatch_async(my_queue, ^{ 
    NSLog(@"test");    // (4) // never been called when realm is used in the same queue 
    }); 
    _connection = nil;    // (5) // without (1) this line stops runloop so (2) and (3) will be called 
} 
+0

Warum erwarten Sie, dass der Aufruf 'CFRunLoopRun()' zurückgibt? Sie rufen nicht 'CFRunLoopStop()' auf, sodass der Runloop ausgeführt wird, bis alle Quellen entfernt wurden. Unter der Annahme, dass nichts anderes verwendet wird, ist die Runloop sehr zerbrechlich. Ich würde auch empfehlen, keinen Runloop auf einem Thread auszuführen, den Sie nicht besitzen, insbesondere Dispatch Queues. Es gibt eine beschränkte Anzahl von Threads, die Service-Dispatch-Warteschlangen so tun, dass sie für einen unbestimmten Zeitraum blockiert werden, z. B. das Starten eines Runloops, das auf den Abschluss von Netzwerkoperationen wartet. Dies kann dazu führen, dass Dispatchwarteschlangen verhungern und möglicherweise Deadlocks verursachen. – bdash

Antwort

0

CFRunLoopRun läuft die Runloop im Standardmodus, bis alle Quellen und Timer entfernt oder CFRunLoopStop heißt. Ihr Code scheint unter der Annahme zu arbeiten, dass niemand sonst eine Runloop-Quelle hinzufügen oder einen Timer auf diesem Runloop registrieren wird und dass alle Runloop-Quellen entfernt werden, wenn Ihre Netzwerkanforderung abgeschlossen ist. Ich glaube nicht, dass es sicher ist, Annahmen über das Verhalten von Code von Drittanbietern zu treffen, egal ob es sich um Realms oder Apples handelt.

Darüber hinaus würde ich davon abraten, einen Runloop in einer Dispatch-Warteschlange auszuführen. Dispatch-Warteschlangen werden von einer begrenzten Anzahl systemeigener Threads bedient, und es ist verpönt, sie für unbestimmte Zeitspannen zu blockieren, beispielsweise während sie auf eine Netzwerkanforderung warten. NSURLConnection lässt Sie glücklich schedule the connection on a different runloop, wie der Runloop des Hauptfadens oder sogar schedule delegate callbacks to happen on a dispatch queue.

Wenn Sie absolut muss weiterhin eine Runloop auf einer Absende-Warteschlange wie diese ausgeführt werden, sollten Sie einige explizite Signal zu bestimmen, wann läuft die Runloop zu stoppen und dann CFRunLoopStop aufzurufen. Ich würde jedoch empfehlen, dies zu vermeiden.

+0

Ich möchte nur verstehen, was Realm mit aktuellen Thread-Laufschleife tut. Ich überprüfe ihre Dokumente und finde keine Erwähnung in ihren Dokumenten über Threading. Ich verstehe, dass Run-Loop-Quellen und Timer überprüft, aber ich bin mir nicht sicher, dass Realm Quellen verwendet und ich verstehe nicht, warum sie Timer verwenden möchten. Aber sie haben Realm mobile Plattform, die für die Verbindung zwischen Client-Realm und Remote verwendet wird + sie senden Nutzungsstatistiken an ihre Server, wahrscheinlich, dass das Problem, weiß ich nicht. – yangand

+0

Ich habe gerade dieses Projekt erhalten und versucht, Realm hinzuzufügen, um zusätzliche Daten zu speichern und die Sperre an einem anderen Ort zu erhalten, indem ich lediglich das lokale Datenbank-Storage-Framework hinzufüge. Verwendet GCD einen Pool von Threads, in denen versandte Warteschlangen zusammengefasst sind? – yangand

+0

Und ja, jetzt muss ich CFRunLoopStop in meiner Netzwerkverbindung didFinishedConnection Delegat Methode aufrufen, nur um aktuelle Laufschleife zu stoppen und CFRunLoopRun zu beenden, aber es funktionierte vor und funktioniert jetzt nicht. – yangand

Verwandte Themen