0

I have an application that creates a background thread for the network messages. The application works nearly perfectly unless the server it connects to closes the connection. I am unsure of why this happens but any advice is greatly appreciated. I've included the snippets of code that can be followed to the problem. If something is vague or more detail is needed please let me know.

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch(eventCode) {
    case NSStreamEventErrorOccurred:
        {
            NSLog(@"NSStreamEventErrorOccurred");

            [self Disconnect:self];
        }
    }
}

- (void)Disconnect:(id)sender {
    [self performSelector:@selector(closeThread) onThread:[[self class]networkThread] withObject:nil waitUntilDone:YES];

    [outputStream close];
    [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream release];
    outputStream = nil;
}

+ (NSThread*)networkThread
{
    // networkThread needs to be static otherwise I get an error about a missing block type specifier
    static NSThread* networkThread = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        networkThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkThreadMain:) object:nil];

        [networkThread start];
    });

    return networkThread;
}

The hang up occurs on the return networkThread line. After executing that line the application seems to hang and freeze and I can't put my finger on why.

Thanks in advance.

EDIT

Here is the snippet of code for CloseThread for those interested

- (void)closeThread
{   
    /*if(!inputStream)
        return;

    [inputStream close];
    [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    [inputStream release];
    inputStream = nil;*/
}
Seb
  • 3,414
  • 10
  • 73
  • 106
  • You have not included the implementation of `-closeThread`, which I suspect is your actual problem. If you just exit the thread, it's highly likely that your `waitUntilDone:YES` never gets notified that it's done and deadlocks. – Lily Ballard Sep 19 '12 at 21:05
  • The reason I haven't added that method is because my break point never gets hit. To confirm it I commented out everything inside so that the function is empty. The code works fine if I manually decide to disconnect on the iPad GUI. – Seb Sep 19 '12 at 21:20
  • Are you running a runloop on that thread? `performSelector:onThread:...` requires that the destination thread have an associated runloop that is processing messages. – Lily Ballard Sep 19 '12 at 23:11
  • I am running it in a runloop. When trying to connect I call the networkThread calling the openThread selector. This does the following: [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [inputStream open]; – Seb Sep 20 '12 at 13:10

1 Answers1

1

I suggest changing:

[self performSelector:@selector(closeThread) onThread:[[self class]networkThread] withObject:nil waitUntilDone:YES];

to:

[self performSelector:@selector(closeThread) onThread:[[self class]networkThread] withObject:nil waitUntilDone:NO];

That is, don't wait.

David H
  • 40,852
  • 12
  • 92
  • 138
  • Looks like this worked. The main reason I wanted to wait until I was finished was because I wan't to make sure that my objects where removed and set to nil before moving forward. – Seb Sep 20 '12 at 13:16
  • The way to achieve synchronization like this (if you really needed it) is send the message and don't do anything else. In the object that gets the message (eventually), do what you want, and in the end either use another performSelectorOnMainThread or use a block, to restart work. – David H Sep 20 '12 at 13:19