How do I create an NSThread that isn't the main thread without performing a selector immediately
Asked Answered
S

4

5

I want to create a worker thread that isn't the main thread so I can call ...

[self performSelector:@selector(doStuff) OnThread:self.myWorkerThread withObject:nil];

... in a bunch of locations in my code. How do I create a thread.. any thread and assign it to a variable so I can use it over and over in my code. NSThread detachNewThreadWithSElector will only create one for the purpose of running that one selector. I need to create a thread and use it somehow.

I am using iOS and need to perform all my CoreData writes on a writerThread. I need to use the same thread (that isn't the main one) every time.

Salvidor answered 30/3, 2012 at 2:37 Comment(0)
M
4

I highly recommend looking into Grand Central Dispatch instead :). You can easily create a dispatch queue via dispatch_queue_create or get one of the existing concurrent threads and send whatever you want to it. It will create the appropriate number of threads based on the workload / OS status, etc. It will look like this:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
    //Do stuff
});

Or you can look into its NS counterpart, NSOperation. I don't know of a way to do this with just NSThread. It seems the only way to set its selector is to init it with one.

EDIT If you want just a thread, just call [[NSThread alloc] init] :p

FURTHER EDIT: iPhone: how to use performSelector:onThread:withObject:waitUntilDone: method?

As per this answer, it is going to be difficult to set up, as every thread needs a "main" function at the time it is created or else it will do nothing...

Makeshift answered 30/3, 2012 at 2:53 Comment(3)
if I performSelectorWithThread:[NSThread mainThread] it works fine but performSelectorWithThread:[[NSThread alloc] init] freezes and doesn't do anything :(.. I tried calling 'start' after allocing it but it does nothing.Salvidor
Apologies: I am frustrated by the extreme lack of documentation. I should not have taken it out here. comment removed.Barbirolli
No problem. It's a common frustration to have. If you have an active question about it though maybe I can help answer it.Makeshift
T
2

It seems like the easiest way would be to use blocks:

void (^now)(void) = ^ {
    NSDate *date = [NSDate date];
    NSLog(@"The date and time is %@", date);
};

and call:

now();

NSBlockOperation or dispatch_async().

See more here: http://pragmaticstudio.com/blog/2010/7/28/ios4-blocks-1

Tweeze answered 30/3, 2012 at 2:57 Comment(2)
I'm on iOS... aren't they mac only?Salvidor
No blocks are used on iOS. What SDK are you using? They are supported in 4 and 5.Tweeze
C
2

If you really want this and not using GCD, then:

NSThread *thr = [[NSThread alloc] initWithTarget:anobject selector:@selector(doStuff) object:nil];

And this will call the appropriate method on your object whenever you want - however, it seems to me that the current implementation of NSThread doesn't permit to change the target and selector.

Cupping answered 30/3, 2012 at 4:28 Comment(2)
Thats backwards to what I want. Periodically I write to core data and I want to do this on a designated thread (on startup) so I don't have to have multiple NSManagedObjectContexts. so I need to performSelectOnThread:<previously designated thread>Salvidor
missing: [thr start]; :)Delineator
Y
1

If you are specifically doing this to interact with Core Data (as your question suggests), and you can require iOS 5 for your app, you might want to investigate the new private queue managed object context added in iOS 5. It creates and manages the thread/dispatch queue for you, and you send it blocks to run on the queue as a way of interacting with it. See the release notes and the WWDC session video for more details.

Update (May 2016): the new API added in iOS 5 was -[NSManagedObjectContext initWithConcurrencyType:]. As of iOS 9, the older initializer has been deprecated, along with the confinement concurrency type that had been the default prior to the introduction of the queue-based concurrency types. So if you're not using queues to manage context access, I'd strongly recommend moving in that direction.

I'd also strongly recommend using the com.apple.CoreData.ConcurrencyDebug launch argument while you're developing, in order to help you catch places where you're breaking the rules.

Yepez answered 30/3, 2012 at 4:22 Comment(1)
Link is dead - this is why you should include some content from the link in your answer.Bontebok

© 2022 - 2024 — McMap. All rights reserved.