Использование потока жизни приложения, отличного от основного потока

У меня есть многопоточное приложение, в котором каждый поток должен выполнять определенную работу, но в определенный момент некоторый код должен выполняться последовательно (например, запись в базу данных sqlite3), поэтому я вызываю этот код для выполнения на главном используя поток:

[self performSelectorOnMainThread:@selector(serialJob:) withObject:object waitUntilDone:YES];

и все шло отлично, за исключением того, что когда этому коду требуется некоторое время, пользовательское взаимодействие с приложением отключается до тех пор, пока этот код не будет завершен, поэтому есть ли способ создать еще один ОДИН поток, который можно запускать в фоновом режиме и вызывать всякий раз, когда Мне нужно это так же, как основной, чтобы я мог заменить предыдущий вызов на:

[self performSelector:@selector(serialJob:) onThread:REQUIRED_THREAD withObject:object waitUntilDone:YES];

этот поток должен быть членом статических данных некоторого класса, к которому должен обращаться весь код.

любая помощь будет очень признательна, и большое спасибо заранее...

3 ответа

Решение

Из-за моего вопроса, что мне нужно заблокировать текущий поток, пока работа с базой данных не будет завершена, я попробовал эти два решения, и они отлично работали. Вы можете использовать критические разделы или NSOperationQueue, и я предпочитаю первый, вот код для них обоих:

Определите некоторый класс DatabaseController и добавьте этот код в его реализацию:

static NSString * DatabaseLock = nil;
+ (void)initialize {
    [super initialize];
    DatabaseLock = [[NSString alloc] initWithString:@"Database-Lock"];
}
+ (NSString *)databaseLock {
    return DatabaseLock;
}

- (void)writeToDatabase1 {
    @synchronized ([DatabaseController databaseLock]) {
        // Code that writes to an sqlite3 database goes here...
    }
}
- (void)writeToDatabase2 {
    @synchronized ([DatabaseController databaseLock]) {
        // Code that writes to an sqlite3 database goes here...
    }
}

ИЛИ чтобы использовать NSOperationQueue вы можете использовать:

static NSOperationQueue * DatabaseQueue = nil;
+ (void)initialize {
    [super initialize];

    DatabaseQueue = [[NSOperationQueue alloc] init];
    [DatabaseQueue setMaxConcurrentOperationCount:1];
}
+ (NSOperationQueue *)databaseQueue {
    return DatabaseQueue;
}

- (void)writeToDatabase {
    NSInvocationOperation * operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(FUNCTION_THAT_WRITES_TO_DATABASE) object:nil];
    [operation setQueuePriority:NSOperationQueuePriorityHigh];
    [[DatabaseController databaseQueue] addOperations:[NSArray arrayWithObject:operation] waitUntilFinished:YES];
    [operation release];
}

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

Это довольно легко сделать, просто порождайте ваш поток и позволяйте ему запускаться через runloop, используя [[NSRunLoop currentRunLoop] run], Это все, что требуется, чтобы иметь возможность использовать performSelector:onThread: с пользовательской темой.

Если вы используете iOS 4 или новее, вам следует рассмотреть возможность использования очередей Grand Central Dispatch вместо потоков. API GCD намного проще в использовании и могут намного лучше использовать системные ресурсы.

Как говорил Свен, загляните в Grand Central Dispatch.

Вы можете создать очередь следующим образом:

dispatch_queue_t myQueue = dispatch_queue_create("com.yourcompany.myDataQueue", NULL);

Теперь вы можете вызывать блоки в этой очереди:

dispatch_async(myQueue, ^{
  // Your code to write to DB.
});

Когда вы закончите, не забудьте освободить очередь:

dispatch_release(myQueue);
Другие вопросы по тегам