2013-05-01 2 views
0

В моем приложении я запускаю сервер в фоновом режиме. Для этого я использую NSOperation. (. Я использовал НОД раньше, но мне нужно, чтобы быть в состоянии остановить его, поэтому я перешел на NSOperation, но я до сих пор не могу понять, каким образом)Сила остановки NSOperation или GCD?

Так по существу, мой NSOperation подкласс выглядит следующим образом:

- (void)main { 
    server_main(var1, var2); 
} 

Так как это сервер, функция server_main в основном не возвращается. Я также не могу контролировать реализацию этой функции.

Время от времени пользователь меняет настройки сервера. Когда это произойдет, я хотел бы остановить и перезапустить сервер. Если я правильно понял, мне нужно сделать что-то вроде if (self.isCancelled) в подклассе NSOperation, но поскольку он будет застревать в функции server_main, я сомневаюсь, что он действительно сработает.

Так как я могу остановить сервер?

Большое спасибо!

ответ

2

Чтобы сделать это правильно видеть Responding to Cancellation Events в параллелизмом Руководство по программированию,, который говорит:

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

Чтобы поддержать отмену в рабочем объекте, все, что вам нужно сделать, - это периодически вызывать метод объекта isCancelled из вашего пользовательского кода и немедленно возвращаться, если он когда-либо возвращается YES.

Это долгий намотанной способ сказать, что я действительно думаю, что вы должны быть в состоянии изменить server_main так, что он либо:

  • Проверить isCancelled периодически или

  • Есть его предоставить блок меток делегата обратного вызова/прогресса, чтобы вы могли сделать это самостоятельно, а также некоторые дополнительные функции/методы, которые вы можете вызвать для отмены server_main, позволяя ему выполнять критический процесс очистки.

Если вы просто начать убивать процессы (если вы даже можете), вы, несомненно, утечка ресурсов или оставить что server_main в неустойчивом состоянии.

Я знаю, что это не тот ответ, который вы ищете, но это способ отмены работы. Сожалею.

+0

Да, я понял ... Я знаю об этом, но проблема в том, что я почему-то не могу изменить 'server_main'. В противном случае я полностью это сделаю. – aforaudrey

+0

@iBlue - Извините. Это перетаскивание, но для 'server_main' фактически требуется, чтобы один из этих двух методов был отменен. (Sigh.) Является ли 'server_main' чем-то, что вы можете заменить тем, что разрешает отмену? (например, некоторые фреймворки могут быть добавлены в виде библиотеки или могут быть скомпилированы исходным кодом как часть проекта, если у вас есть источник, который вы можете отредактировать) или вы застряли с ним, как есть? – Rob

+0

Да, к сожалению, я застрял в этом, как есть ...><Спасибо. – aforaudrey

0

вы можете использовать метод

- (void)setSuspended:(BOOL)suspend 

на NSOperationQueue? А перед добавлением новой операции проверьте, приостановлена ​​ли очередь с isSuspended?

Edit: Здесь параметр приостановить Если ДА, то очередь останавливается планирование очереди операций для выполнения. Если «НЕТ», очередь начинает снова планировать операции. Обсуждение Этот метод приостанавливает или возобновляет выполнение операций. Приостановка очереди не позволяет этой очереди запускать дополнительные операции. Другими словами, операции, которые находятся в очереди (или добавлены в очередь позже) и еще не выполняются, не запускаются до тех пор, пока очередь не будет возобновлена. Приостановка очереди не останавливает уже запущенные операции.

Операции удаляются из очереди только после их завершения. Однако, чтобы закончить выполнение, сначала необходимо запустить операцию. Поскольку приостановленная очередь не запускает никаких новых операций, она не удаляет какие-либо операции (включая отмененные операции), которые в настоящее время находятся в очереди и не выполняются.

Надеюсь, это поможет вам.

+0

Итак, когда я приостанавливаю очередь, она останавливает операцию, содержащуюся ни на что? Но операция просто приостановлена, а не остановлена? Мне нужно остановить его и начать новую копию ... Спасибо! – aforaudrey

+0

Кажется, что это не заставляет остановить работу. – aforaudrey

+0

Я обновил свой ответ. Проверь это. –

0

Вы можете попробовать этот код:

@interface Canceller 
{ 
    BOOL _shouldCancel; 
} 
- (void)setShouldCancel:(BOOL)shouldCancel; 
- (BOOL)shouldCancel; 
@end 

@implementation Canceller 
- (void)setShouldCancel:(BOOL)shouldCancel { 
    _shouldCancel = shouldCancel; 
} 
- (BOOL)shouldCancel { 
    return _shouldCancel; 
} 
@end 

static void test(int a){ 
    static Canceller * canceller = nil; 

    if(q){ 
     [canceller setShouldCancel:YES]; 
     [canceller release]; 
     dispatch_suspend(q); 
     dispatch_release(q); 
     q=nil; 
    } 
    canceller = [[Canceller alloc] init]; 
    q=dispatch_get_global_queue(0,0); 
    dispatch_async(q,^ { 
     while(![canceller shouldCancel]){NSLog(@"query %d",a);sleep(2);} 
    }); 

} 

Надеется, что это помогает.

+1

Эй, спасибо за ответ. Но если вы не поймете, что происходит с кодом (который, как я полагаю, из другого сообщения SO), я не думаю, что это работает для моего дела. Если вы думаете иначе, любая разработка будет оценена. – aforaudrey

+0

Неужели вы добавляете NSOperation в очередь операций или нет? Если вы добавляете в операцию, вы можете вызвать метод [queue cancelalloperations]; – 2013-05-01 12:44:46

+0

, что не помогает, по-видимому, потому что они то же самое – aforaudrey

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