2012-01-06 3 views
3

Я хочу создать фоновый поток на iPhone, который выполняет некоторый код каждые 10 мсек. Но прежде, чем я заблудился в руководстве по программированию параллелизма и руководстве по программированию потоков для apple снова, я хотел спросить, может ли кто-то здесь помочь мне. Что я хочу сделать:Worker Thread iOS

  • Создание фона рабочего потока
  • Trigger выполнение метода каждый 10 мс. (Возможно, с помощью NSTimer в этом потоке?)
  • Положить меньше нагрузки на основной поток приложения, как это возможно

В моем понимании подклассов NSThread и писать свой собственный основной метод в данном подклассе следует сделать трюк. Таким образом, я не использовать NSTimer для интервалов обновления, но что-то вроде:

[NSThread sleepForTimeInterval: 0.01]; 

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

Вопрос: Как настроить поток для использования таймера? Я не вижу, как я могу присоединить NSTimer к этим рабочим потокам Run Loop?

+0

Nsoperation - одноразовый объект. Как только он исполнится, он исчез. Вы можете воссоздать рабочие объекты по таймеру. – Moshe

ответ

11

Это можно сделать, используя метод, который вы начертите, но посмотрели ли вы на использование Grand Central Dispatch? Это может сделать некоторые из этого намного проще:

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
dispatch_async(backgroundQueue, ^{ 
    while ([self shouldKeepProcessingInBackground]) { 
     [self doBackgroundWork]; 
     usleep(1e4); 
    } 
}) 

Вы также можете использовать источник отправки таймера, чтобы сделать работу периодически:

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
dispatch_source_t timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, backgroundQueue); 
dispatch_source_set_timer(timerSource, dispatch_time(DISPATCH_TIME_NOW, 0), 0.01*NSEC_PER_SEC, 0*NSEC_PER_SEC); 
dispatch_source_set_event_handler(timerSource, ^{ 
    [self doBackgroundWork]; 
}); 
dispatch_resume(timerSource); 
+1

не используют usleep(). Вместо этого используйте любой из встроенных таймеров, таких как примитивы, поскольку они намного эффективнее (как показано на втором примере). – bbum

+0

Второе предложение Эндрю Мэдсенса; используя центральную диспетчерскую отправку, dispatch_resume (timerSource); и dispatch_suspend (timerSource); отлично зарекомендовал себя в моих целях –

1

Вы можете легко использовать GCD (Grand Central Dispatch) для этого. Сначала создайте селектор, который будет вызываться в фоновом режиме. Отсюда вызывается любой метод, который вы хотите.

- (void)backgroundSelector 
{ 
    // do whatever you want to do 
    [self performSelector:@selector(backgroundSelector) withObject:nil afterDelay:0.01]; 
} 

После этого просто запустите этот метод в первый раз, как этот

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 
    [self backgroundSelector]; 
}); 

Позвольте мне знать, если это работает для вас.

+0

нет, поскольку мы говорим о периодических операциях здесь –

2

NSRunLoop - недостающее звено.

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

NSRunLoop - довольно маленький класс - проверьте его и соответствующие образцы.

+0

, вот что я пытался понять. но я не могу это понять :(Как настроить цикл выполнения потоков, чтобы повторить? откуда? исходный поток? Что вы подразумеваете под «из вашей записи в потоке» - начало основного метода моего подкласса NSThread? hm, я буду искать примеры для справки –

+0

, вам нужно дать ему источник и/или таймер и/или направить его на выполнение. Говорить, что это нужно запустить, вероятно, короткий ответ. Если он не имеет ввода, то он останавливается (и тогда поток закроется). Для этого вы будете взаимодействовать с циклами выполнения из потока, к которому он привязан. Я смотрел на это: CFRunLoop - это гораздо лучшее введение в тему, и есть множество примеров (см. OS X ссылка). «Запись вашего потока» относится к ее точке входа. Это часть программы, в которой был создан поток, и ваш обратный вызов/сообщение сделано, так как у вас есть подклассы NSThread, '-main'. Это – justin

0

Это довольно просто и чисто, если вы делаете это с помощью NSThread. Не нужно подклассифицировать его.

- (void)backgroundStuff { 
    while (!self.cancelThread) { 
     // do your work 
     [NSThread sleepForTimeInterval:0.01]; 
    } 
} 

Просто обычная функция. cancelThread - это переменная-член, которую вы объявляете. Запустите его с

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

и вы можете cancle поток в любое время с самим собой.cancelThread = true;

+0

это решение, которое я использую сейчас, и оно недостаточно работает. Вот почему я хочу лучшего backgr ound thread, включая конфигурацию Run Loop или все, что требуется. –

Смежные вопросы