2

I'm having this wierd problem with the app freezing at a certain point. I'm guessing its got to do with how I'm using NSConditionLock.

Theres a library I have been given to use, which consists of a series of survey questions, but it works in such a way that it races directly to the last question without accepting answers, hence the need to pause the thread and accept input from the user.

I haven't used it before so maybe someone could help if I'm implementing it wrongly? Please let me know if the code provided is insufficient.

- (void)viewDidLoad
{
    [super viewDidLoad];
//INITIALISE CONDITION LOCK WITH CONDITION 0
     condition=[[NSConditionLock alloc]initWithCondition: 0];
}


- (IBAction)startPressed:(UIButton*)sender {
if (sender.tag == 1) {
//START BACKGROUND THREAD
 surveyThread = [[NSThread alloc] initWithTarget:self selector:@selector(runProjecttest)      object:nil];
        [surveyThread start];
}
else
{
 //DO SOME STUFF AND THEN UNLOCK
 [condition unlockWithCondition:1];
}
}


- (void) runProjecttest:(AbstractTask *)rendertask
{
// DO STUFF AND SHOW UI ON MAIN THREAD, THEN LOCK
[self performSelectorOnMainThread:@selector(showUI:) withObject:task waitUntilDone:YES];
 [condition lockWhenCondition: 1];
}

EDIT: In short, I want the Objc equivalent of this java snippet...

this.runOnUiThread(showUI);
    try 
    {
        //SLEEP         
        Thread.sleep(1000*60*60*24*365*10);
    } 
    catch (InterruptedException e) 
    {
                   //WAKE
        setResponse(at,showUI);
    }

EDIT 2: ShowUI method on Paul's request.

 [self removePreviousSubViews];

 switch ([task getType]) {
        case SingleChoiceType:
        {
            NSLog(@"SingleChoiceType");
            isMultipleChoice = NO;
            [self addSingleChoiceView:nil];
            break;
        }
        case TextType:
        {
            NSLog(@"TextType");
            self.txtTextType.keyboardType=UIKeyboardTypeDefault;
            [self addTextTypeView:nil];

            break;
        }
...more cases
}

-(void)addTextTypeView:(NSSet *)objects
{
    self.txtTextType.text = @"";
    CGRect frame = self.txtQuestionType.frame;
//    frame.size = [self.txtQuestionType sizeThatFits: CGSizeMake(self.txtQuestionType.frame.size.width, FLT_MAX)];
        frame.size.height = [self textViewHeightForAttributedText:self.txtQuestionType.text andWidth:self.txtQuestionType.frame.size.width andTextView:self.txtQuestionType];


    self.txtQuestionType.frame=frame;

    self.textTypeView.frame = CGRectMake((self.view.frame.size.width - self.textTypeView.frame.size.width)/2, ( self.txtQuestionType.frame.origin.y+self.txtQuestionType.frame.size.height), self.textTypeView.frame.size.width, self.textTypeView.frame.size.height);

    [self.view addSubview: self.textTypeView];
}
Paulw11
  • 108,386
  • 14
  • 159
  • 186
Akash Malhotra
  • 1,106
  • 1
  • 17
  • 30

1 Answers1

0

I agree with BryanChen, I think you may have another issue. Without details on the survey library, it is impossible to confirm, but assuming that it is a UIViewController than accepts touch inputs to progress through a series of questions, it is hard to see why it is a threading issue - it simply shouldn't advance without user interaction.

That aside, your use of NSCondtionLock doesn't look right either.

Essentially an NSConditionLock has an NSInteger that represents the current 'condition', but just think of it of a number. There are then two basic operations you can perform -

lockWhenCondition:x will block the current thread until the 'condition' is 'x' and the lock is available. It will then claim the lock.

unlockWithCondition:y releases the lock and sets the condition to 'y'

There are also methods to set timeouts (lockBeforeDate) and try to claim the lock without blocking (tryLock, tryLockWhenCondition).

To synchronise two threads, the general pattern is

  1. Initialise Lock to condition 'x'
  2. Thread 1 lockWhenCondition:x -This thread can claim the lock because it is x
  3. Thread 2 lockWhenCondition:y - This thread will block because the lock is x
  4. Thread 1 completes work, unlockWithCondition:y - This will enable Thread 2 to claim the lock and unblock that thread

Your code looks strange, because you are starting a thread in your if clause but unlocking in an else clause. I would have thought you would have something like -

-(IBAction)startPressed:(UIButton*)sender {
    if (sender.tag == 1) {
    //START BACKGROUND THREAD
     surveyThread = [[NSThread alloc] initWithTarget:self selector:@selector(runProjecttest)      object:nil];
        [surveyThread start];
        [condition:lockWithCondition:1];     //  This will block until survey thread completes
        [condition:unlockWithCondition:0];   //  Unlock and ready for next time
    }

}

- (void) runProjecttest:(AbstractTask *)rendertask
{
// DO STUFF AND SHOW UI ON MAIN THREAD, THEN LOCK
[condition lockWhenCondition: 0];
[self performSelectorOnMainThread:@selector(showUI:) withObject:task waitUntilDone:YES];
[condition unlockWithCondition:1];
}

BUT This looks like a recipe for deadlock to me, because you are performing the showUI selector on the main thread that is blocked waiting for the survey thread to complete.

Which brings us back to the question, what does showUI do and why is it skipping directly to the end?

Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • thanks for the insight. showUI adds and removes subviews from the main view based on a switch case. – Akash Malhotra Apr 29 '14 at 08:11
  • What drives the switch statement? – Paulw11 Apr 29 '14 at 08:12
  • the type of the question fetched from the library, like a numeric question, or a date type etc.. – Akash Malhotra Apr 29 '14 at 08:17
  • OK. I think I am getting it now. You are using `addSubview`/`removeSubview`? What triggers the call to removeSubview? Perhaps you should present the appropriate view controller either using a `UINavigationController` or modally? Can you update the question to show the `showUI` method? – Paulw11 Apr 29 '14 at 08:42
  • I am not presenting a new controller, its just add and remove subviews from self.view . – Akash Malhotra Apr 29 '14 at 09:35
  • Where do you remove the views? – Paulw11 Apr 29 '14 at 09:41
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/51661/discussion-between-paulw11-and-akash-malhotra) – Paulw11 Apr 29 '14 at 09:44