簡體   English   中英

NSTimer在目標C中阻止主線程-iPad編程

[英]NSTimer in objective c blocking main thread - ipad programming

我在Objective-C中使用NSTimer定期運行后台進程(間隔為1分鍾),該進程檢查是否有未保存的數據並通過Web服務提交到數據庫。 在重新啟動Web服務器之前的一種特定情況下,此過程可以正常運行而不會阻塞主應用程序的流。

當Web服務器啟動時,后台進程正在嘗試連接到服務器,只是掛在那兒,直到服務器完全啟動並可以訪問為止。 當掛斷電話時,它也阻塞了主要應用程序的流程並凍結了整個屏幕。 當Web服務器完全啟動時,掛斷過程將恢復,並且主應用程序也將恢復工作。

誰能讓我知道掛斷后台進程時為什么主應用程序間歇性凍結。

以下代碼啟動計時器

- (void) startSync{
    syncTimer = [NSTimer scheduledTimerWithTimeInterval:60
                                         target:self
                                       selector:@selector(syncExtSys:)
                                       userInfo:nil
                                        repeats:YES];
}

每60秒調用一次以下方法, saveAgendaToDb方法調用將調用Web服務:

- (void) syncExtSys:(NSTimer *) theTimer{
    UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:[NSBundle mainBundle]];
    AgendaItemViewController *agendaItemViewController = [storyboard instantiateViewControllerWithIdentifier:@"AgendaItemViewController"];
    RollCallViewController *rollCallViewController = [storyboard instantiateViewControllerWithIdentifier:@"RollCallViewController"];

    for(int i=0;i<agenda.count;i++){
        unsavedAgenda = [agenda objectAtIndex:i];
        if(unsavedAgenda !=nil && [unsavedAgenda.dirtyFlag isEqualToString:@"Y"] && [self checkNetworkStatus]){

            NSLog(@"agenda out of sync = %@ %@",unsavedAgenda.measureType,unsavedAgenda.measureNum);
            [agendaItemViewController saveAgendaToDb:[agendaItemViewController createDictForAgenda:unsavedAgenda]:unsavedAgenda];
        }
    }
    for(int i=0;i<_rollCall.count;i++){
        Member *member = [_rollCall objectAtIndex:i];

        if(member !=nil && [member.dirtyFlag isEqualToString:@"Y"] && [self checkNetworkStatus]){

            [rollCallViewController saveRollCall:[rollCallViewController createRollCall]];
            break;
        }
    }

    [self calcDirtyFlag];
}

代碼調用Web服務

-(void) saveAgendaToDb:(NSMutableDictionary*) agendaDictionary:(AgendaItem*) agenda{
    NSError *error;
    CommVotesAppDelegate *delegate = (CommVotesAppDelegate *)[[UIApplication sharedApplication] delegate];
    @try{

        NSString *postUrlString = [NSString stringWithFormat:@"%@%@:%@%@%@/%@",@"http://",delegate.prop.serverName,
                                   delegate.prop.port,delegate.prop.urlPattern,delegate.prop.saveAgendaMethod,delegate.prop.objectType];
        NSURL *postUrl = [NSURL URLWithString:postUrlString];
        NSMutableURLRequest *urlRequestPost = [[NSMutableURLRequest alloc] initWithURL:postUrl];
        NSData *postData = [NSJSONSerialization dataWithJSONObject:agendaDictionary options:0 error:&error];
        [urlRequestPost setHTTPMethod:@"POST"];
        [urlRequestPost setValue:@"text/plain" forHTTPHeaderField:@"Accept"];
        [urlRequestPost setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
        [urlRequestPost setHTTPBody: postData];
        // NSLog(@"After calling webservices");
        NSData *returnData = [ NSURLConnection sendSynchronousRequest: urlRequestPost returningResponse: nil error: &error ];
        NSString *returnString = [[NSString alloc] initWithData:returnData encoding: NSUTF8StringEncoding];
        NSLog(@"Response after calling save agenda web service = %@",returnString);
       [delegate dirtyFlagCalc:returnString :[error localizedDescription]:agenda];
    }@catch(NSException *nserror){
      NSLog(@"Error while sending agenda through webservices = %@",nserror.debugDescription);
    }@finally {
        NSLog(@"Inside finally block of agenda saving ");
        [delegate saveDataToDisk];
    }
}

計時器在主線程上觸發。 如果syncExtSys:方法沒有立即完成,它將掛起主線程。

您的情況是,您想做一些可能需要一段時間的事情,但是您希望結果顯示在主線程的UI中。 解決此問題的一些好方法是對Grand Central Dispatch執行以下操作之一:

  1. 使用計時器分派源對后台隊列進行處理,然后分派結果以顯示在主隊列上。
  2. 堅持使用NSTimer,但是將可能需要在syncExtSys:中花費一些時間的所有內容分發到后台隊列,然后在完成時將結果分發回到主隊列。
  3. 在syncExtSys:中使用所有非阻塞調用:

您的錯誤是此調用: sendSynchronousRequest 簡而言之就是這樣。 幾乎沒有任何理由同步發送Web請求-現在您知道了為什么不應該這樣做。 它是同步的! 這意味着它在我們等待時會阻塞線程-如果等待很長時間,就會有很長的阻塞。 這是主線程,因此我們阻止了用戶界面,計時器以及所有內容。

只需切換到異步請求並正確使用委托回調,一切都會很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM