2013-05-01 57 views
0

在我的应用程序中,我在后台运行服务器。我正在使用NSOperation这样做。 (我用GCD之前,但我需要能够阻止它,所以我切换到NSOperation,但我仍然无法弄清楚如何)强制停止NSOperation或GCD?

所以基本上,我NSOperation子类看起来是这样的:

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

由于这是一个服务器,server_main函数基本上不返回。我也无法控制该功能的实施。

偶尔,用户会更改服务器的设置。发生这种情况时,我想停止然后重新启动服务器。如果我理解正确,我需要在NSOperation子类中执行类似if (self.isCancelled)的操作,但由于它会卡在server_main函数中,所以我怀疑它实际上会起作用。

那么我该如何停止服务器?

非常感谢!

回答

2

要做到这一点正确地看到Responding to Cancellation Events并发编程指南,这表示在:

虽然NSOperation类提供为客户取消操作,确认取消事件是需要自愿的方式。如果一项行动彻底终止,可能无法收回已分配的资源。因此,预计操作对象将检查取消事件,并在操作中间发生时正常退出。

要支持操作对象中的取消操作,您只需定期从自定义代码中调用对象的isCancelled方法,并在返回YES时立即返回。

这是说的长篇大论方式,我真的觉得你需要能够改变server_main,以便它可以:

  • 检查isCancelled定期或

  • 有它提供一个回调/进度委托方法块,这样你就可以自己做到这一点,并且可以调用一些额外的函数/方法来取消server_main,让它进入关键的清理过程。

如果你刚开始杀死进程(如果你甚至可以),你肯定会泄漏资源或留下server_main处于不一致的状态。

我知道这不是您要找的答案,但这是取消操作的方式。抱歉。

+0

是的,我想......我知道这一点,但问题是我不能修改'server_main'出于某种原因。否则,我会完全做到这一点。 – aforaudrey 2013-05-01 13:07:17

+0

@iBlue - 对不起。这是一个阻力,但'server_main'实际上需要提供这两种技术之一才能被取消。 (感叹。)'server_main'是你可以用允许取消的东西来替换的东西吗? (例如,某些框架可以作为库添加,或者可以将其源代码编译为项目的一部分;如果您有源代码,则可以编辑它)或者您坚持使用它? – Rob 2013-05-01 13:17:10

+0

是的,可悲的是我坚持它,因为它是...“<虽然感谢。 – aforaudrey 2013-05-01 17:41:41

0

您可以使用NSOperationQueue的

- (void)setSuspended:(BOOL)suspend 

方法?在添加新操作之前,请检查队列是否使用isSuspended挂起?

编辑:这里参数暂停 如果是YES,则该队列停止调度排队的操作来执行。如果否,则队列再次开始调度操作。 讨论 该方法暂停或恢复执行操作。暂停队列可防止该队列启动其他操作。换句话说,在队列恢复之前,阻止队列中(或稍后添加到队列中)并且尚未执行的操作启动。暂停队列不会停止正在运行的操作。

只有当它们完成执行时,才从队列中删除操作。但是,为了完成执行,必须首先开始操作。由于暂停队列不会启动任何新操作,因此它不会删除当前正在排队并且未执行的任何操作(包括取消的操作)。

希望它可以帮助你。

+0

所以当我暂停一个队列时,它会停止包含的操作,不管是什么?但是,手术是否仅仅暂停,不停止?我需要停下来,开始一个新的副本......谢谢! – aforaudrey 2013-05-01 12:17:36

+0

似乎它不强制停止运行操作.. – aforaudrey 2013-05-01 12:26:27

+0

我已经更新了我的答案。检查这个。 – 2013-05-01 12:37:29

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 2013-05-01 12:40:11

+0

是否在操作队列中添加NSOperation?如果你正在添加一个操作队列,那么你可以调用一个方法[queue cancelalloperations]; – 2013-05-01 12:44:46

+0

这并没有明显的帮助,因为它们是相同的东西 – aforaudrey 2013-05-01 13:09:39