Как переключаться между фоновыми и основными потоками - PullRequest
0 голосов
/ 08 июля 2019

Я никогда раньше не использовал фоновые темы.У меня есть трудоемкие вычисления, в настоящее время выполняющиеся в основном потоке, который добавляет вывод данных в TERecord.Мой рабочий процесс по существу идет:

запуск длинного процесса… обновление графического интерфейса… запуск длинного процесса… обновление графического интерфейса… и т. Д.

В нескольких местах, где код производит (строковые) выходные данные, я обновляю пользовательский интерфейсвызывая мой метод addToRecord, показанный здесь:

-(void)addToRecord:(NSString*)passedStr:(BOOL)updateUI
 {
    NSRange endRange;
    // add the passed text...
    endRange.location = [[theOutputView textStorage] length];
    endRange.length = 0;
    [theOutputView replaceCharactersInRange:endRange withString:passedStr];

if(updateUI) // immediate GUI update needed...
    {
    // scroll window contents to BOTTOM of page...
    endRange = NSMakeRange([[theOutputView string] length],0);
    [theOutputView scrollRangeToVisible:endRange];

    [theOutputView display];
    }
}

Пока он выполняет свою работу, весь мой пользовательский интерфейс остается без ответа до тех пор, пока процесс, конечно, не завершится.Я знаю, что должен выполнять тяжелую работу на фоновом потоке, который я никогда раньше не использовал.Я выяснил часть проблемы при создании фонового потока, как показано ниже:

-(IBAction)readUserInput:(id)sender
{   
// irrelevant code snipped for brevity
if([self checkForErrors] == NO)
    {
    [runButton setEnabled:NO];
    [self performSelectorInBackground:@selector(runWorkThread)     withObject:nil];
    }
}

-(void)runWorkThread
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
    [self runLongProcess];
[pool drain];
}

, но я просто не понимаю, как вызывать основной поток каждый раз, когда код встречает мой метод addToRecord,тогда как вернуть управление фоновому потоку?Другая возможность может состоять в том, чтобы удалить код updateUI из моего метода addToRecord и просто иметь основной поток, вызывающий этот код каждую секунду или около того, по таймеру?

Буду очень признателен за любой совет и пример кода.Спасибо!

1 Ответ

0 голосов
/ 10 июля 2019

Вместо использования performSelectorInBackground вы можете использовать Dispatch framework (также называемый GCD), который является предпочтительным способом обработки параллельной работы.В Dispatch уже есть пул фоновых потоков, которые вы можете использовать.Чтобы переключить поток, вы вызываете dispatch_async() следующим образом:

    dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
        // :
        // Do your background work here
        // :
        dispatch_async(dispatch_get_main_queue(), ^{
            // :
            // Now you are back in the main thread
            // :
        });
    });

Первый параметр - это идентификатор очереди, который предоставляется вам либо dispatch_get_global_queue(), который возвращает одну из «рабочих» очередей, либо dispatch_get_main_queue() который возвращает основную очередь.Последний параметр - это блок кода, который выполняется в выбранной очереди.

При запросе параллельной очереди с использованием dispatch_get_global_queue() вы указываете Качество обслуживания , которое определяет приоритет вашего кода.иметь по отношению к другой работе.См. Документацию для получения дополнительной информации и возможных значений.

Подробнее об отправке

...