0

在这里提出一些问题后,我决定运行这样的服务器:

@implementation Server
-(id)init
{
if (self = [super init])
{   
    shouldRun = true;
    __block Server* blocksafeSelf = self; // should prevent retain cycle

    myServer = ^() {
                    dispatch_async(dispatch_get_main_queue(), ^{
            NSString* currentText = controller.output.text;
            controller.outputTextField.text = [currentText stringByAppendingString:@"Server ready. \n"];
        });

        while (blocksafeSelf.shouldRun) {
           int bytes_received = recvfrom(...);
            if (bytes_received > 0) {
                switch (TYPE OF RECEIVED PACKET) {
                    case 1: {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            NSString* currentText = controller.outputTextField.text;
                            controller.outputTextField.text = [currentText stringByAppendingString:@"S: Received Typ 1 "];
                        });
                        [blocksafeSelf methodToDealWithPacket:(PACKETTYPE*) buffer];
                        break;
                    }
                    ...
                    default: {
                       ...
                    }
                }

            }
        }

return self;
}
@synthesize shouldRun;

对应的 .h 文件:

@interface Server : NSObject {
    ServerBlock myServer;
    ....
}
@property BOOL shouldRun;
....
@end

现在我有一个 ViewController,它具有 Server 作为属性,并在其实现中使用以下方法:

// called when the user clicks the stop button
- (IBAction) clickedStop
{
    if(theServer != nil) {
        theServer.shouldRun = false;
    }
}

但是,当我单击停止按钮时,服务器不会退出他的 while 循环。为什么?

编辑:这是在 ViewController 中启动服务器的方式:

// called when the user clicks the start button
  - (IBAction) clickedStart
   {
   dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

    if (...) { // all needed data has been entered
        // start server here
        if(theServer == nil) {
            theServer = [[SNPTServer alloc] initWithHost:serverIP.text AndPort:    [serverPort.text intValue] AndViewController:self];
            dispatch_async(queue, theServer.myServer);
        }
    }

}

如您所见,我对上面的构造函数进行了一些更改。

4

1 回答 1

2

只有当您的 while 循环的主体类似于以下内容时,我的答案才会起作用(我会假设它确实如此)

while (blocksafeSelf.shouldRun) {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                             beforeDate:[NSDate distantFuture]];
}

在这种情况下,仅将 shouldRun 设置为 NO 是不够的。while 循环在不同的线程/runLoop 上运行,因此必须发生事件以导致 run loop 弹出,以便再次检查条件。

最简单的方法是从运行服务器的线程将 shouldRun 设置为 NO。我会做这样的事情:

myServer = ^() {
    self.runThread = [NSThread currentThread]; // runThread declared elsewhere
    while (blocksafeSelf.shouldRun) {
          ....
        }
    }

然后当你想取消它时:

- (IBAction) clickedStop
{
    if ([NSThread currentThread] == theServer.runThread) {
        if(theServer != nil) {
            theServer.shouldRun = NO;
        }
    } else if (theServer.runThread) {
        [self performSelector:_cmd
                     onThread:theServer.runThread
                   withObject:nil
                waitUntilDone:NO];
    }
}
于 2012-11-15T22:11:14.543 回答