target-c / iphone: как установить, что все методы какого-либо объекта будут выполняться в определенном потоке? - PullRequest
0 голосов
/ 23 сентября 2010

вот что я хочу:

создайте объект, который «живет» в своем собственном потоке, все методы должны выполняться в этом потоке.

т.е.:

// 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

Я читал о потоках и циклах выполнения. Я создал новый поток для метода init, его точкой входа является метод runloop. Метод runloopMethod просто устанавливает самые основные вещи, необходимые для запуска NSRunLoop, и запускает его.

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

это работало нормально, но когда я вызываю метод (то есть: [myObject method1];) из основного потока, он запускает его в основном потоке, откуда я это знаю? Хорошо, потому что method1 выполняет несколько операций, которые блокируют пользовательский интерфейс , Я перенаправил вызов таким образом:

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

это работает, но этот способ ограничивает меня, также у меня есть несколько вопросов к вам:

Я понял, что если я нахожусь в X-потоке и вызываю метод некоторого объекта, он будет выполняться в X-потоке. Я думаю, что вызов метода будет добавлен (не уверен, что это слово) в цикл выполнения X-потока. не так ли?

Есть ли способ установить это: любой вызов методов моего объекта будет выполняться в потоке объекта? (без всего этого).

также, это правильный путь для того, что я делаю? method1, method2 и т. д. являются синхронизированной версией моих функций .. поэтому они будут блокировать пользовательский интерфейс. Вот почему я предполагаю, что наличие другого потока - это .

спасибо за чтение!

кстати. я не использую GCD, так как мне нужно поддерживать iOS 3

Ответы [ 2 ]

1 голос
/ 23 сентября 2010

Код времени выполнения диспетчеризации метода Objective C не имеет механизма (AFAIK), который бы неявно определял, следует ли выполнять универсальный вызов метода в потоке, отличном от текущего, поэтому вам придется реализовать собственный механизм явного фонового вызова, так как вы сделал, используя executeSelector.

Если вы установите для waitUntilDone значение YES при вызове фонового потока из основного потока, вы все равно заблокируете пользовательский интерфейс.

Если вы хотите, чтобы метод method1 работал в фоновом режиме, а не блокировал пользовательский интерфейс, установите для параметра waitUntilDone значение NO, и фоновый поток должен сообщить основному потоку о завершении (или о чем-либо еще) с помощью executeSelectorOnMainThread.

В качестве альтернативы вы можете использовать очереди операций для отправки сообщений в цикл выполнения фонового потока.

0 голосов
/ 23 сентября 2010

Я предполагаю, что вы пытаетесь использовать потоки для выполнения фоновых задач, чтобы поддерживать отзывчивость интерфейса. Это хорошо, но это будет очень сложный подход. Попробуйте вместо этого:

1) Из основного потока запустить новый поток:

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

2) Напишите methodThatTheThreadShouldRun и делайте в ней все, что вам нужно. Он будет выполнен в той теме, которую вы только что создали. Когда он закончится, вызовите threadIsFinished в главном потоке:

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

3) Наконец, напишите 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
}
...