Как отправить селекторы или блоки в NSRunLoop для выполнения? - PullRequest
13 голосов
/ 15 октября 2010

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

Какя могу настроить NSRunLoop для сна после инициализации?После чего, как я могу сигнализировать циклу выполнения, чтобы он проснулся и что-то сделал?

Я пытался прочитать Руководство по программированию Threading для iOS, но я хотел бы избежать настройки классов как пользовательскихвходные классы и использовать что-то более легкое, например performSelector:onThread:

Могу ли я установить таймер, чтобы он работал вечно с этого момента, чтобы цикл выполнения не заканчивался?код:

// Initialization Code...

do {
    sleepUntilSignaled();
    doWorkSentToThisThread();
while (!done);

Куда я отправляю работу в виде performSelector:onThread: сообщения.Было бы еще лучше, если бы я мог отправить цикл выполнения блоком вроде: ^{[someObj message]; [otherObj otherMsg];}, но я был бы счастлив с performSelector, так как я почти уверен, что это возможно без большого дополнительного кодирования.

Спасибо!

Ответы [ 3 ]

10 голосов
/ 15 октября 2010

У вас есть все необходимые части вместе в вашем вопросе.Вы запускаете поток и запускаете его runloop.Если вам нужен поток, чтобы сделать что-то, вы можете использовать performSelector:onThread: в главном потоке, чтобы сделать это.

Есть одна вещь с runloop, которую вы должны знать, хотя: она не будет работать, если она не имеетисточник входного сигнала или таймер подключен к нему.Просто подключите таймер к циклу выполнения, который срабатывает некоторое время в далеком будущем, и все готово.

// Initialization code here

[NSTimer scheduledTimerWithTimeInterval: FLT_MAX
                                 target: self selector: @selector(doNothing:)
                               userInfo: nil repeats:YES];

NSRunLoop *rl = [NSRunLoop currentRunLoop];
do {
    [rl runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!done);

Используя performSelector:onThread:withObject:, вы также можете передать свой блок фоновому потоку.Все, что вам нужно сделать, это написать метод где-нибудь, который принимает блок в качестве параметра и запускает его:

@interface NSThread (sendBlockToBackground)
- (void) performBlock: (void (^)())block;
@end

@implementation NSThread (sendBlockToBackground)
- (void) performBlock: (void (^)())block;
{
    [self performSelector: @selector(runBlock:) 
                 onThread: self withObject: block waitUntilDone: NO];
}

- (void) runBlock: (void (^)())block;
{
    block();
}
@end

Но, возможно, вам следует использовать очередь отправки вместо всего этого.Для этого требуется меньше кода и, вероятно, также меньше служебной информации:

dispatch_queue_t myQueue = dispatch_queue_create( "net.example.product.queue", NULL );
dispatch_async( myQueue, ^{
    // Initialization code here
} );

// Submit block:
dispatch_async( myQueue, ^{
    [someObject someMethod: someParameter];
} );

Очередь отправки, созданная с использованием dispatch_queue_create, является последовательной очередью - все отправленные ей блоки будут выполняться в том же порядке, в котором они поступили, один задругой.

2 голосов
/ 23 декабря 2011

Рассмотрите возможность использования NSConditionLock. Он предназначен для подобных задач. Представьте, что у вас есть очередь с данными. Первый поток добавляет данные в очередь, второй поток ожидает данные и обрабатывает их.

id condLock = [[NSConditionLock alloc] initWithCondition:NO_DATA];

//First thread
while(true)
{
    [condLock lock];
    /* Add data to the queue. */
    [condLock unlockWithCondition:HAS_DATA];
}

//Second thread
while (true)
{
    [condLock lockWhenCondition:HAS_DATA];
    /* Remove data from the queue. */
    [condLock unlockWithCondition:(isEmpty ? NO_DATA : HAS_DATA)];

    // Process the data locally.
}
0 голосов
/ 15 октября 2010

Я думаю, вы можете использовать NSInvocationOperation с NSOperationQueue.

...