views:

46

answers:

2

Hi guys,

here is what i want:

create an object that 'lives' in its own thread, all the methods should be executed in that thread.

i.e:

// i'm in the main thread
MyClass *myObject = [ [MyClass alloc] init ]; // it creates its own thread
[myObject method1];  // should execute the method1 in myObject's thread  
[myObject method2];  // should execute the method2 in myObject's thread
[myobject release];  // should deallocate everything that is used for myObject and remove myObject's thread

i have been reading about threads and runloops. I created a new thread on the init method, its entry point is the runloop method. The runloopMethod just set the most basic stuff needed for running a NSRunLoop and runs it.

aThread = [[NSThread alloc] initWithTarget:self selector:@selector(runloopMethod) object:nil];  
[aThread start]; 

it worked fine, but when i call a method ( i.e: [myObject method1];) from the main thread it runs it on the main thread, how do i know it?, well, because method1 performs several operations that blocks the UI. What i have done is to redirect the call in this way:

// on MyClass.m
-(void) method1 {
    if ([NSThread currentThread] != aThread) {
        [self performSelector:@selector(method1) onThread:aThread withObject:nil waitUntilDone:YES];
    }else {
        // do my stuff
    }

it's working, but this way limits me, also i have some questions for you:

i have realized that if i'm in X-thread and call a method of some object, it will be executed in X-thread. I think that the method call will be added (not sure if it's the word) to the X-thread's runloop. right?

Is there a way to set that: any call to my object's methods will be executed on the object's thread? (without doing all this stuff).

also, is it the correct way for what am i doing? method1, method2, and so on are the sync version of my functions..so they will block the UI. that' why i assume having another thread is the way.

thanks for reading!.

btw. i'm not using GCD since i need to support iOS 3

A: 

I'm guessing you are trying to use threads to run background tasks in order to keep the UI responsive. That's good, but this would be a very difficult approach. Try this instead:

1) From the main thread, fire off a new thread:

[NSThread detachNewThreadSelector:@selector(methodThatTheThreadWillRun)
                         toTarget:nil
                       withObject:nil];

2) Write methodThatTheThreadShouldRun and do whatever you need to do in it. It will be executed in the thread you just created. When it finishes, have it call a threadIsFinished on the main thread:

- (void)methodThatTheThreadWillRun {
    MyClass *myObject = [ [MyClass alloc] init ];
    [myObject method1];
    [myObject method2];
    [myobject release];
    [self performSelectorOnMainThread:@selector(threadIsFinished)];
}

3) Finally, write threadIsFinished:

- (void)threadIsFinished {
    // do whatever you need to do here: stop a spinner, etc.
    // this will be invoked by the background thread but will
    // execute on the main thread
}
alexantd
@yep Alexantd, i want to keep the UI responsive. The problem about using detachNewThreadSelector or performSelectorInBackground is that it does not configures a run loop.
subzero
+1  A: 

The Objective C method dispatch runtime code has no mechanism (AFAIK) to determine implicitly whether to do a generic method call on a different thread than the current one, so you will have to implement your own explicit background call mechanism, as you did, using performSelector.

If you set waitUntilDone to YES on your call to your background thread from the main thread, you will still block the UI.

If you want your method1 to run in the background and not block the UI, set waitUntilDone to NO, and have to background thread inform the main thread about completion (or anything else) using performSelectorOnMainThread.

You might alternatively be able to use operation queues to send messages to your background thread's run loop.

hotpaw2
hotpaw2, thanks for your answer. yesp, i realized about the YES/NO flag on performSelector...., it was an error when posting my code. i'm unfamiliar with the operations queues, so far it seems that it's a kind of pool to fire several methods/operations at the same time, the interesting point is: "You might alternatively be able to use operation queues to send messages to your background thread's run loop.", you meant, using performSelector:onThread... ?
subzero