В приложении MacOS у меня есть фоновый поток, выполняющийся с одной строкой кода, занимающий много времени.Как отменить блок? - PullRequest
0 голосов
/ 03 января 2019

В приложении Какао Objective-C, которое я разрабатываю, у меня есть NSTableView с делегатом, который реализует tableViewSelectionDidChange. В реализации метода делегата я поместил фоновую последовательную очередь, реализованную с помощью GCD, которая обрабатывает загрузку выбранного в данный момент объекта в таблице, чтобы он отображался в подробном NSView, который находится справа от таблицы. Мое желаемое поведение состояло бы в том, что, если фоновая нить не закончилась и в левой таблице есть новый выбор, я хотел бы отменить его и начать новый поток для нового выбора. Я нашел очень элегантное решение с использованием GCD здесь , которое использует:

dispatch_block_cancel(work);

Проблема в том, что, как сказано в ссылке:

"Следует отметить, что dispatch_block_cancel не имеет преимущественного значения. Если рабочий блок находится в середине длительной операции, dispatch_block_cancel не будет принудительно завершать его. Для этого мы должны периодически проверять для отмены с dispatch_block_testcancel. Вот пример: "

for (...) {
    /* do some work */
    [NSThread sleepForTimeInterval:0.2];

    if (dispatch_block_testcancel(work) != 0) {
        /* exit gracefully */
        return;
    }
}

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

if (dispatch_block_testcancel(work) != 0) {
        /* exit gracefully */
        return;
}

потому что поток заблокирован из-за длительной однострочной операции. Можно ли надеяться, что кто-нибудь предложит какую-то стратегию, желательно с использованием GCD? Я знаю о NSOperation и NSOperationQueue, но прежде чем научиться их использовать, я хотел бы убедиться, что у них нет проблем с отменой операций в середине 1-строчного оператора, как, очевидно, делает GCD. Большое спасибо за любую помощь.

Ответы [ 2 ]

0 голосов
/ 21 июня 2019

Вы могли бы преобразовать вызов dylib в вызов службы xpc, который фактически запустил бы вызов в другом процессе, который позволил бы вам его убить.сторонняя библиотека, завернув ее в службу xpc, позволила нам изящно справиться с ее ошибками.

https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html

0 голосов
/ 03 января 2019

Это не решаемо. Неважно, какой инструмент вы используете (GCD против NSOperation). Невозможно принудительно остановить выполняемую операцию. Это оставило бы память в неизвестном состоянии. Решение состоит в том, чтобы дождаться завершения строки кода, а затем, если блок был отменен, отбросить результат. Если строка кода очень дорогая, так что вам действительно нужно ее завершить (а не просто игнорировать ее результат), вам придется заменить библиотеку кодом, который проверяет флаг отмены.

...