Синхронное разрешение Bonjour с NSNetService (почему требуется так много времени, чтобы вернуть управление из цикла выполнения?) - PullRequest
1 голос
/ 11 июля 2011

Я пытаюсь выполнить Bonjour для разрешения имени службы синхронно, поэтому я пытаюсь выяснить, как правильно ожидать вызова netServiceDidResolveAddress () NSNetService.

Мой код выглядит так:

service = [[NSNetService alloc] initWithDomain:@"local." type:@"_myservice._tcp" name:[self name]];
[service retain];
[service setDelegate:self];
waitingOnResolution = true;
[service resolveWithTimeout:5.0];

for (int i=0;i<5;i++) {
    DebugLog(@"resolve: resolve iteraton %u\n", i);
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; // run loop for one second
    DebugLog(@"resolve: resolve iteraton %u (after run loop)\n", i);
    if (!waitingOnResolution) break;   
}

// continue processing...

А вот моя функция, которая обрабатывает разрешение разрешения:

- (void)netServiceDidResolveAddress:(NSNetService *)sender
{
    // do processing...
    waitingOnResolution = false;
    CFRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]); // has no effect
}

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

Что на самом деле происходит, так это то, что разрешение происходит довольно быстро, и я вижу, что код в netServiceDidResolveAddress () завершен, но затем постоянно происходит нежелательное 5–6-секундное ожидание, пока элемент управления не возвращается из runUntilDate, и я вижу «... (после цикла выполнения) оператор отладки.

Я огляделся на нескольких досках объявлений и увидел похожие вопросы, но их решения (такие как использование CFRunLoopStop), похоже, не имеют никакого эффекта.

Вот пример регистрации, которую я получаю:

2011-07-11 09:38:07.267 MyProgram[1822:707] resolve: resolve iteraton 0
2011-07-11 09:38:07.299 MyProgram[1822:707] netService: netServiceDidResolveAddress function ended

[5+ second delay]

2011-07-11 09:38:12.907 MyProgram[1822:707] resolve: resolve iteraton 0 (after run loop)

Если кто-то может рассказать мне о другом способе использования разрешения NSNetService для получения синхронного результата или рефакторинга моего кода, связанного с runloop, чтобы избежать этой (казалось бы, созданной ОС) задержки 5-6 секунд, я был бы признателен.

Ответы [ 2 ]

1 голос
/ 12 июля 2011

Вы действительно не должны этого делать.Разрешение сети является асинхронным по уважительной причине: может занять много времени для выполнения разрешения, и в большинстве случаев вы не хотите блокировать ваш поток на время.Если вы выполняете разрешение в главном потоке, вы действительно не хотите делать это синхронно.В Mac OS X длительная операция, блокирующая основной поток, приведет к вращающемуся пляжному мячу.На iOS сторожевой таймер может полностью убить ваше приложение.

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

Так как вы не объясняете, почему вы пытаетесь делать это синхронно, я не могу помочь намного больше, но имейте в виду, что Какао управляется событиями.Разбейте ваши синхронные шаги на состояния и позвольте обратным вызовам из Какао на каждом этапе продвигать ваш конечный автомат вперед.Это не будет выглядеть так же хорошо, как построчная процедурная функция, но будет поддерживать отзывчивость вашего пользовательского интерфейса и позволит избежать неприятных обходных путей.

0 голосов
/ 06 августа 2013

Просто удалите CFRunLoopStop и все должно работать нормально. Остановка NSRunLoop остановит любые другие события на этом NSThread. Я сделал то же самое (без остановки RunLoop) для синхронного разрешения некоторых NSNetServices, и все работало нормально.

...