iPhone - отмена поставленных в очередь операций GCD - PullRequest
1 голос
/ 10 марта 2011

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

Я не могу найти способ отменить поставленную в очередь задачу, тогда я подумал, что мог бы создать логический флаг, называемый, например, quitRender и test, чтобы увидеть, является ли этот флаг истинным, и выйти из рендера, но это не работает, и мой Объяснение таково: флаг quitRender имеет значение «НЕТ», когда задачи запускаются, так как они выполняются в блоках, и блоки замораживают значения, какими они были при запуске, блоки не увидят изменения и никогда не выйдут.

Затем я попробовал другой подход: я создаю метод, подобный

- (BOOL) cancelRender {
    return quitRender;
}

, который будет запускать и отправлять блоку текущее значение переменной, но, очевидно, блоки по-прежнему будут видеть NO для quitRender.

Я что-то упустил? Как мне сделать эту работу?

спасибо.

Ответы [ 3 ]

4 голосов
/ 10 марта 2011

__ модификатор хранилища блоков может быть полезен в такой ситуации.

__block BOOL quitRender = NO;

Он позволяет изменять переменную из блоков, и блоки могут видеть измененную переменную.Но будьте осторожны, так как доступ к переменной __block не является потокобезопасным.

атомарные функции предпочтительны для обеспечения доступа к переменной как атомарной.

Также вы можете использовать ivar из блоков,Если переменная является свойством с атомарным атрибутом, она доступна для потокового доступа.

Как использовать переменную quitRender?

EDIT :

__block int32_t quitRender = 0;

/* set */
OSAtomicOr32(1, &quitRender);

/* test */
if (quitRender) {
1 голос
/ 01 ноября 2011

Вы на правильном пути, сделав переменную quitRender переменной класса хранения __block, поскольку тогда основная часть кода может изменить ее, чтобы указать, что ожидающая операция должна быть отменена.

Тем не менее, нет никаких проблем с тем, чтобы сделать его безопасным для работы с потоками, как предлагали другие, поскольку с самого начала отмена является по своей природе неаккуратной. Вы можете начать выполнение блока (и выполнить проверку отмены) непосредственно перед тем, как переменная будет установлена ​​в значение ИСТИНА, и в этом случае вы проиграете гонку, даже если вы выполняли обтекание OSAtomic(), так что вы могли бы также установить его и забудьте об этом, так как в этом случае флаг отмены может перейти только из состояния FALSE в TRUE.

Если управление хранилищем классов блоков по какой-то причине является проблемой (скажем, у вас есть несколько операций, которые потенциально могут быть отменены), тогда поместите флаг отмены в любую структуру данных, которой управляет очередь, и просто проверьте ее. Если сама очередь является правильным местом для указания того, что все операции в очереди отменены, то вы также можете использовать dispatch_{set,get}_specific(), чтобы сохранить это в самой очереди. НТН.

0 голосов
/ 10 марта 2011

Если вы хотите выйти из всех задач данного класса, вы можете попробовать сделать флаг quitRender изменяемой статической глобальной переменной BOOL, которую код блока не должен замораживать.

Вы можете переносить методы получения и установкивокруг статических глобальных переменных, чтобы сделать код чище.

...