Ich versuche, eine Methode aus einer Klasse zu verwenden, die ich irgendwo heruntergeladen habe. Die Methode wird im Hintergrund ausgeführt, während die Programmausführung fortgesetzt wird. Ich möchte nicht zulassen, dass die Programmausführung fortgesetzt wird, bis diese Methode beendet ist. Wie mache ich das?Warten auf das Ende eines Threads in Objective-C
Antwort
Ich würde vorschlagen, Aufruf der Klassenmethode in Ihrer eigenen Methode, und legen Sie einen booleschen, sobald es abgeschlossen ist. Für zB:
BOOL isThreadRunning = NO;
- (void)beginThread {
isThreadRunning = YES;
[self performSelectorInBackground:@selector(backgroundThread) withObject:nil];
}
- (void)backgroundThread {
[myClass doLongTask];
// Done!
isThreadRunning = NO;
}
- (void)waitForThread {
if (! isThreadRunning) {
// Thread completed
[self doSomething];
}
}
Wie Sie warten behandeln wollen, bleibt Ihnen überlassen: Vielleicht Polling mit [NSThread sleepForTimeInterval: 1] oder ähnliches, oder selbst eine Nachricht jeder Laufschleife sendet.
Meine erste Neigung ist es nicht zu tun, was Sie vorschlagen. Die Technik, die ich zuvor verwendet habe, ist, dem Thread einen Selektor für eine Methode im Ursprungsobjekt (die sich im Hauptthread befindet) zu geben. Wenn der zweite Thread gestartet wird, wird der Hauptthread weiterhin ausgeführt, aber auf dem Display wird eine Besetztzeichenanzeige angezeigt. Dadurch kann die Benutzerinteraktion bei Bedarf fortgesetzt werden.
Wenn der zweite Thread beendet wird, bevor er beendet wird, ruft er den Selektor auf dem Hauptthread auf. Die Methode, auf die der Selektor verweist, entfernt dann den Busy-Indikator von der Anzeige und teilt dem Haupt-Thread mit, was er aktualisiert hat. Er nimmt alle Daten auf, die der zweite Thread erzeugt hat.
Ich habe dies erfolgreich für eine App verwendet, die auf einen Webdienst zugreift (im zweiten Thread) und dann die Anzeige aktualisiert, sobald Daten zurückgegeben werden, ohne sie zu sperren. Dies macht die Benutzererfahrung viel schöner.
Dies ist ein schönes System für UI-Updates; Sie können ein Schmerz sein. – v01d
Verwenden Sie ein NSOperationQueue, wie diese
(aus dem Gedächtnis vergeben so keine kleinere Fehler - Sie werden die Grundidee erhalten):
// ivars
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
// count can be anything you like
[opQueue setMaxConcurrentOperationCount:5];
- (void)main
{
[self doStuffInOperations];
}
// method
- (void)doStuffInOperations
{
// do parallel task A
[opQueue addOperation:[[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSomething:) object:@"a"] autorelease]];
// do parallel task B
[opQueue addOperation:[[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSomething:) object:@"b"] autorelease]];
// do parallel task C
[opQueue addOperation:[[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSomething:) object:@"c"] autorelease]];
[opQueue waitUntilAllOperationsHaveFinished];
// now, do stuff that requires A, B, and C to be finished, and they should be finished much faster because they are in parallel.
}
- (void)doSomething:(id)arg
{
// do whatever you want with the arg here
// (which is in the background,
// because all NSOperations added to NSOperationQueues are.)
}
Ich weiß, dass ich diese Frage nicht gestellt habe, aber das war, was ich mit meiner App gesucht habe, da ich Race Conditions hatte und ich wusste, dass sie schneller waren, als der Code konnte . Dies löste mein großes Problem. Also danke, mein Herr, ich denke, das sollte als die richtige Antwort markiert werden, weil es keine Arbeit verwendet und eine Thread-sichere Kodierung mit der Ios-Bibliothek beinhaltet. – Rob
Zweitens, was Rob sagte, das ist genau das, was ich gesucht habe! – AdamM
@AdamM - überprüfen Sie die andere Antwort, die ich heute gepostet habe. Es ist ein viel sauberer Weg, es zu tun und GCD wird für alle iOS 4 und höher unterstützt. Ein bemerkenswerter Vorteil dieser Methode besteht darin, dass Sie keine Abstürze mehr bekommen, wenn Objekte von Ihnen entfernt werden, da GCD alle Objekte, auf die Sie verweisen, automatisch speichert und freigibt. – jpswain
Hier ist eine andere Art und Weise, es zu tun GCD mit:
- (void)main
{
[self doStuffInOperations];
}
- (void)doStuffInGCD
{
dispatch_group_t d_group = dispatch_group_create();
dispatch_queue_t bg_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(d_group, bg_queue, ^{
[self doSomething:@"a"];
});
dispatch_group_async(d_group, bg_queue, ^{
[self doSomething:@"b"];
});
dispatch_group_async(d_group, bg_queue, ^{
[self doSomething:@"c"];
});
// you can do this to synchronously wait on the current thread:
dispatch_group_wait(d_group, DISPATCH_TIME_FOREVER);
dispatch_release(d_group);
NSLog(@"All background tasks are done!!");
// **** OR ****
// this if you just want something to happen after those are all done:
dispatch_group_notify(d_group, dispatch_get_main_queue(), ^{
dispatch_release(d_group);
NSLog(@"All background tasks are done!!");
});
}
- (void)doSomething:(id)arg
{
// do whatever you want with the arg here
}
Meine Technik ist zu prüfen, ob die Aufgabe (wenn der Hintergrund-Thread beendet ist) ausgeführt werden kann, und wenn es nicht dann ich GCD laufen kann wieder verwenden, um zu versuchen nach einer Verzögerung:
- (void)doSomething
{
if (/* is the other thread done yet? */) {
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self doSomething];
});
return;
}
// do something
}
Mehrere technische Möglichkeiten, Multi-Threads zu synchronisieren, wie NSConditionLock
(Mutex-Sperre), NSCondition
(Semaphor). Aber sie sind gemeinsame Programmierkenntnisse für andere Sprachen (Java ...) neben Objective-c. Ich ziehe es run loop
(Sonder in Cocoa) einzuführen Thread zu implementieren verbinden:
NSThread *A; //global
A = [[NSThread alloc] initWithTarget:self selector:@selector(runA) object:nil]; //create thread A
[A start];
- (void)runA
{
[NSThread detachNewThreadSelector:@selector(runB) toTarget:self withObject:nil]; //create thread B
while (1)
{
if ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) //join here, waiting for thread B
{
NSLog(@"thread B quit...");
break;
}
}
}
- (void)runB
{
sleep(1);
[self performSelector:@selector(setData) onThread:A withObject:nil waitUntilDone:YES modes:@[NSDefaultRunLoopMode]];
}
Für solche Fälle ich in der Regel NSCondition Klasse.
//this method executes in main thread/queue
- (void)waitForJob
{
id __weak selfWeak = self;
NSCondition *waitHandle = [NSCondition new];
[waitHandle lock];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
[selfWeak doSomethingLongtime];
[waitHandle signal];
});
//waiting for background thread finished
[waitHandle waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:60]];
}
- 1. Bash-Threading: Warten auf das Ende aller Job-Threads funktioniert nicht?
- 2. Die beste Methode zum Warten auf das Ende des Rückrufs
- 3. beschäftigt warten threads in java
- 4. Können mehrere Threads auf dasselbe Objekt warten?
- 5. C#: Warten auf alle Threads zu vervollständigen
- 6. C# Warten auf mehrere Threads zu beenden
- 7. Sind Threads auf einen Sperr-FIFO warten?
- 8. C# Multithreading-Problem warten auf Threads
- 9. JavaScript: Warten auf Ende für bestimmte Zeit
- 10. Setzen Sie das Limit auf UITextField in ObjectiveC
- 11. Warten auf das Beenden eines Timers in Java
- 12. AMF0 Parser in ObjectiveC
- 13. Warten auf eine Teilmenge von Threads in einer Java-Thread
- 14. warten auf MessagingCenter in Xamarin Forms
- 15. Warten Sie das Ende von Teilprozessen mit mehreren parallelen Jobs
- 16. Kann ich auf das TLS eines VERSCHIEDENEN Threads zugreifen?
- 17. Garbage Collection eines Objekts, das Verweis auf lebendige Threads enthält
- 18. Std :: Future oder Std :: shared_future auf mehrere Threads warten
- 19. Multi Threading, Thread läuft, ohne auf andere Threads zu warten
- 20. Wie verhindert man das Umschalten eines Threads?
- 21. C++ 11 Thema: Mehrere Threads auf eine Zustandsvariable warten
- 22. Warten Sie, andere Ansicht Animation Ende
- 23. Warten, bis gepoolte Threads abgeschlossen sind
- 24. Java - Warten auf Threads von Drittanbietern zu beenden
- 25. Holen Sie sich das Ende eines Arrays
- 26. Warten, bis Kind Threads beendet: Java
- 27. Wie warten, bis mehrere Threads abgeschlossen sind?
- 28. AngularJS warten auf alle async Anrufe innerhalb foreach Ende
- 29. ObjectiveC - Anzeigefenster durch verteilte Objekte
- 30. Wie entferne ich das Ende eines NSMutableString?
Ich tat dies, und es funktioniert, aber es verhindert auch, dass das HUD angezeigt wird. –
Sie könnten NSTimer verwenden, um Benutzeroberflächenupdates abzufragen und zu behalten, die korrekt funktionieren. Alles hängt davon ab, was Sie brauchen. Für eine einfache Aufgabe und dann aktualisieren Dereks Antwort wäre sauberer und weniger lästig. – v01d
Für eine Spielengine oder etwas mehr Echtzeit kann ein Timer ohnehin schon vorhanden sein. Wenn du dann einen Thread losschickst und vergisst, ist es vielleicht mehr, was du brauchst. – v01d