iOS - убедить NSOperation уступить другим потокам, прежде чем начинать долгую и явно нерушимую задачу? - PullRequest
1 голос
/ 31 декабря 2011

У меня низкоприоритетный PDF-чертеж NSOperation.Я использую функцию CGContextDrawPDFPage, чтобы нарисовать страницу.

Насколько я могу судить, приложение не будет переключаться на другой поток, пока выполняется функция CGContextDrawPDFPage.Я полагаю, мне нужно разбить мой графический контекст на несколько меньших контекстов, чтобы обойти это.Но у меня все еще есть одна проблема - как я могу убедить операцию позволить другим потокам выполнять свои задачи перед началом этого розыгрыша?То, как все настроено прямо сейчас, приложение рисует страницу сразу, хотя приоритет потока установлен на ноль.

Вот код, который добавляет NSOperation в очередь:

MyNSOperationSubclass* op = [[MyNSOperationSubclass alloc]initWithStuff: stuff];
[op setThreadPriority:0.];
[self.drawingQueue addOperation:op];

Вот некоторый код в MyNSOperationSubclass:

-(void) drawStuff {
    NSLog(@"drawStuff");
    @autoreleasepool {
        // some code to setup the graphics context and PDF page here
        CGContextDrawPDFPage(context, page);
        [self finish];  // finishes the NSOperation
    }   
}

-(void) main {
    NSLog(@"main");
    @autoreleasepool {
        [self drawStuff];
    }

}

-(void) start {
    self.isExecuting = YES;
    [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
}

, что случается так, что, хотя приоритет потока установлен на ноль, код установки настолько быстр, что NSOperation попадает в вызов CGContextDrawPDFPage прямо какоперация началась.Но как только этот вызов начался, поток не уступит другим потокам, пока не завершится.Таким образом, операция рисования происходит сразу же, что противоположно тому, что я хочу сделать.

РЕДАКТИРОВАТЬ: После более тщательного рассмотрения первый ответчик прав, что вызов CGContextDrawPDFPage не всегда препятствует потоку дать,Но даже при не параллельной операции у меня все еще есть проблема, заключающаяся в том, что она быстро завершается, вместо того, чтобы ждать, когда произойдут другие вещи с более высоким приоритетом.

РЕДАКТИРОВАТЬ 2: Очевидно, я не понимаю, как потокприоритеты работы.После изменения его на непараллельную операцию приоритет потока операции равен 0,5, хотя я и вызвал [op setThreadPriority: 0] перед добавлением его в очередь.

1 Ответ

2 голосов
/ 31 декабря 2011

Итак, первая мысль состоит в том, что ваш поток не может избежать "уступки" другим потокам. Переключение контекста является преимущественным здесь. Так что вы можете поговорить о том, почему вы считаете, что эта тема не приносит результатов. У вас здесь может быть еще одна большая проблема с другой работой, которую вы ожидаете сделать.

Во-вторых, когда вы устанавливаете приоритет потока для этой операции, вы не устанавливаете приоритет этого нового потока, который вы создаете здесь:

[NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];

Это новый поток с обычным приоритетом.

Но отступив от этого на секунду, почему бы просто не сделать эту операцию не параллельной и позволить вашему NSOperationQueue управлять потоком за вас? При необходимости очередь создаст новый поток для вас (и применит ваш приоритет потока, который вы просили).

В качестве альтернативы, если вам все еще не требуется поддержка iOS3, вы можете просто использовать глобальную очередь GCD с низким приоритетом для этой работы (или направить свою собственную очередь GCD в эту глобальную очередь, если вам нужен более точный контроль над порядком и при этом все еще требуется все это сделано с низким приоритетом).

Итак, подумайте над тем, чтобы NSOperationQueue или GCD справились с этим для вас. И подумайте о , почему вы думаете, что этот поток мешает другой работе. Это, вероятно, какая-то большая проблема.

Надеюсь, это поможет.

...