在这里提出一些问题后,我决定运行这样的服务器:
@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);
}
}
}
如你所见,我已经将构造函数改变了一点。
答案 0 :(得分:2)
我的回答只有在你的while循环的主体看起来类似于以下内容时才有效(我会假设它)
while (blocksafeSelf.shouldRun) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
}
在这种情况下,仅将shouldRun设置为NO是不够的。 while循环在不同的线程/ runLoop上运行,因此必须发生一个事件导致运行循环弹出,以便再次检查条件。
最简单的方法是从运行服务器的线程中将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];
}
}