質問

I am trying to create a login page that displays a waiting page while attempting. it has an UIActivityIndicatorView runs on main thread and another thread doing the connection. The code works fine when I uncomment NSLog, but it keeps running when I comment it out. Can anyone explain to me why it doesn't exist the while loop when there is no NSLog? it is a bit complicated. I have a control class that prepare the websocket command and fires it if and only if the websocket is successfully connected.

The action flow is like this:

LoginButton is clicked -> rootView calls [_spinner startAnimating]; -> attempting connecting to websocket -> send log in command when successfully connected.

rootView has to animate the spinner and wait for the response.

  [_spinner startAnimating];
  [NSThread detachNewThreadSelector:@selector(attampingWS) toTarget:self withObject:nil];


  - (void) attampingWS {
     while ([connection isAttamptingWS] && ![connection isConnectedToWebSocket]) {
        /** waiting until it's done **/
        //      NSLog(@"?");
     }
     if ([connection isConnectedToWebSocket]) {
           [self proceedLogin];
           [_spinner performSelectorOnMainThread:@selector(stopAnimating) withObject:nil waitUntilDone:NO];
     }
  }

in connection class:

  @property(nonatomic) NSTimer *attampConnectionTimeOut;
  @property(nonatomic) NSTimer *attampConnection;
  @property BOOL isConnectedToWebSocket;

  - (BOOL) isAttamptingWS {
     return [_attampConnection isValid];
  }

  - (BOOL) isWaitingForResponse {
     return [_waitingForResponse isValid];
  }
  /** this method is redirected from websocket by using delegation **/ 
  - (void)dbConnectionDidConnected:(websocket *)connection {
     [self _terminateAttamptingConnection];
     [self setIsConnectedToWebSocket:TRUE];
  }
役に立ちましたか?

解決

Can anyone explain to me why it doesn't exit the while loop when there is no NSLog?

Your code (invisibly) uses the main thread's run loop to process connection and timer callbacks. Those callbacks control the connection object's state and, as a result, the loop condition.

When removing the NSLog call the status cannot change as the main thread is blocked and the runloop cannot process its sources.

When inserting the call again, NSLog's implementation polls the runloop (maybe to communicate with the asl server). Within the call to NSLog the run loop can dispatch delayed actions, timers or connection callbacks, as dbConnectionDidConnected:. In this method the loop condition is becomes false and the loop exits as soon as the call to NSLog returns.

他のヒント

You should never use an empty loop to sync between threads, it will waste a lot CPU time and more importantly, as you have found your loop won’t exit. Because the compiler will optimize the code and you will never get correct result of [connection isAttamptingWS].

But to solve this exact problem (to see why this would happen) I think you can add volatile keyword to the return value of isAttamptingWS.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top