1

In my main starting thread I need to pause the code and start a new thread and wait until I get user input. Then Id like to discard the new thread made and go back to where the main thread left off. But whats happening is that the new thread is called but the main thread keeps going with the code. How do I deal with this without interfering with the user being able to use the interface buttons? I think that maybe another nscondition needs to be made in my if(moveCount == 2) statement? Or that my main thread needs to wait for a signal from my other thread notifying user input is received.

ADDITIONAL NOTE: I would also like the original thread paused in such a way that I can still use my 2 UIButtons in my interface.

MORE ADDITIONAL NOTES AS TO THE QUESTIONS IM RECEIVING: This is a game I'm making. Somewhere mid code means in my main thread in one of my methods. This method decides which direction I'm moving in then i get a tag difference, then make an attack. But sometimes 2 attacks can be made so its at this point the user has 2 buttons to click on the screen to decide which attack to make.

Also its quiet clear to me that I should not pause the main thread now. If so what is the alternative? Thanks

NSCondition and NSThread

@property (strong, nonatomic) NSCondition *condition;
@property (strong, nonatomic) NSThread *aThread;

In my viewDidLoad create the following.

// create the NSCondition instance
self.condition = [[NSCondition alloc]init];

// create the thread
self.aThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadLoop) object:nil];

somewhere mid code..

if(moveCount == 2){

        [self.aThread start];
    }

   // I need to get captureDecision from user from 2 buttons before continue.. How do I pause this thread when aThread is started. Then when capture decision is received discard aThread and start here.

    NSLog(@"Capture Decision = %d", captureDecision);
    if(captureDecision == 1){

        tagDifference = newButton.tag - currentButton.tag;

    }else{

        tagDifference = currentButton.tag - newButton.tag;

    }
}

aThread Method

-(void)threadLoop{

    NSLog(@"Thread Loop Triggered");
    while([[NSThread currentThread] isCancelled] == NO)
    {
        [self.condition lock];
        while(captureDecision == 0)
        {
            [self.condition wait];
        }

        [self.condition unlock];
    }
    [NSThread exit]; //exit this thread when user input is received
}
4GetFullOf
  • 1,738
  • 4
  • 22
  • 47
  • Just to clarify: you want to freeze everything in the main thread except for the two buttons. Correct? – Lawrence H Dec 04 '13 at 23:36
  • 2
    **blocking** the main thread is ALWAYS a bad idea. have it show a spinner and wait for a callback before proceeding but don't block it -- users will hate it AND the os won't like it => it may kill your app if you block it too long – Daij-Djan Dec 05 '13 at 00:08
  • This is the first time I have ever heard someone trying to block the main thread. – Chris Dec 05 '13 at 02:11
  • Consider disabling components/functions until the background thread finishes. You should never intentionally halt the main thread. – Chris Dec 05 '13 at 02:12
  • @LawrenceH Correct I want to get the user input but have these 2 buttons available to get user input while the main thread is paused. – 4GetFullOf Dec 05 '13 at 02:13

2 Answers2

5

What you are requesting is not possible, the main thread IS the one that handles user interactions, whenever you "halt" the main thread the interface becomes unresponsive.

Based on apple's documentation:

The main run loop of your app is responsible for processing all user-related events. The UIApplication object sets up the main run loop at launch time and uses it to process events and handle updates to view-based interfaces. As the name suggests, the main run loop executes on the app’s main thread. This behavior ensures that user-related events are processed serially in the order in which they were received.

Which means that if you halt the main thread you won't be able to. https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW14

(Unless there is some strange way to make a background thread handle the user interactions which i might not be aware of, but still its pretty strange)

As others have told you here, your approach is far from optimal. Questions you have to ask yourself are, in what part of the code do you want to wait for a certain event to occur, and for what purpose.

If you give us a more detailed explanation of what you want to achieve then we can offer you a much better solution.

EDIT:

What kind of game is it? turn based? something that gets drawn constantly like with a timer. Basically you have to use functions, for example, if it was a card game, you would lay all the cards and wait for user input, when the user hits the button you would run "calculate outcome function" and make the proper changes in the board and wait for the next input.

If you want to pause the thread i would assume it is because something is running constantly, there is a special timer that syncs with the screen called CADisplayLink

https://developer.apple.com/LIBRARY/IOS/documentation/QuartzCore/Reference/CADisplayLink_ClassRef/Reference/Reference.html

You can even "pause" this timer to wait for an input from the user.

BTW, if you DONT want to let the user interact with the interface until an event occurs all you have to do is, self.view.userInteractionEnabled = NO; this disables all interactions on the screen until you set it back to "YES".

EDIT 2:

The way you change the flow varies on what you are using to make your game, OpenGL? Quartz2D? simple views?

It kinda feels you are a bit lost, you might wanna start from here:

http://www.raywenderlich.com/tutorials (Scroll down to the making games part)

Pochi
  • 13,391
  • 3
  • 64
  • 104
  • So my main thread is just tearing through a bunch of code. (Its a game) sometimes the user will be able to make more then one move. If that occurs the user needs to input data before it can do the calculations. This is why i want to halt the main thread. If this is not the correct way what is a better solution? – 4GetFullOf Dec 05 '13 at 02:18
  • I have added a clearer explanation to the question. Hoepfully it helps. – 4GetFullOf Dec 05 '13 at 02:32
-1

It looks like you are going about this wrong. By design the main thread should not be blocked. You should use some sort of callback/delegate from your background thread to your main thread to set your tag decision. I'd provide a bit more info/examples, but I'm not really sure what you trying to achieve or where your "somewhere mid code" section takes place. I thought the main thread, but then you call a selector to be performed on the main thread.

InfalibleCoinage
  • 588
  • 13
  • 21
  • true, perhaps should have been a comment. I wanted it to be an answer, but the question seemed to be all over the place – InfalibleCoinage Dec 05 '13 at 01:45
  • somewhere mid code = in my main thread in one of my methods. This method decides the which direction I'm moving in then i get a tag difference, then make an attack. But sometimes 2 attacks can be made so its at this point the user has 2 buttons to click on the screen to decide which attack to make. I hope that its clearer. I will add this to my question. – 4GetFullOf Dec 05 '13 at 02:22