2

我遇到了这个奇怪的问题,应用程序在某个时候冻结。我猜它与我的使用方式有关NSConditionLock

我已经使用了一个库,它由一系列调查问题组成,但它的工作方式是直接跑到最后一个问题而不接受答案,因此需要暂停线程并接受来自用户。

我以前没有使用过它,所以如果我错误地实施它,也许有人可以提供帮助?如果提供的代码不足,请告诉我。

- (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];
}

编辑:简而言之,我想要这个 java 片段的 Objc 等价物......

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

编辑 2:应 Paul 的要求 ShowUI 方法。

 [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];
}
4

1 回答 1

0

我同意 BryanChen 的观点,我认为您可能还有另一个问题。没有调查库的详细信息,无法确认,但假设它是一个 UIViewController 而不接受触摸输入以通过一系列问题,很难理解为什么它是一个线程问题 - 它根本不应该推进无需用户交互。

除此之外,您的使用NSCondtionLock看起来也不正确。

本质上 anNSConditionLock有一个 NSInteger 代表当前的“条件”,但只要把它想象成一个数字。然后,您可以执行两个基本操作 -

lockWhenCondition:x将阻塞当前线程,直到“条件”为“x”并且锁可用。然后它将要求锁定。

unlockWithCondition:y释放锁并将条件设置为'y'

还有一些方法可以设置超时(lockBeforeDate)并尝试在不阻塞的情况下申请锁(tryLock, tryLockWhenCondition)。

要同步两个线程,一般模式是

  1. 将锁初始化为条件'x'
  2. 线程 1 lockWhenCondition:x- 该线程可以申请锁,因为它是 x
  3. 线程 2 lockWhenCondition:y- 该线程将阻塞,因为锁是 x
  4. 线程 1 完成工作,unlockWithCondition:y- 这将使线程 2 能够获得锁并解除对该线程的阻塞

您的代码看起来很奇怪,因为您在 if 子句中启动了一个线程,但在 else 子句中解锁。我原以为你会有类似的东西 -

-(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];
}

但是这对我来说似乎是一个死锁的秘诀,因为您正在主线程上执行 showUI 选择器,该主线程被阻塞等待调查线程完成。

这让我们回到了这个问题,它做了showUI什么以及为什么它直接跳到最后?

于 2014-04-29T07:41:35.787 回答