Как перестать выполнять селектор в фоновом режиме? - PullRequest
1 голос
/ 14 февраля 2011

У меня есть некоторый класс А. В этом классе у меня есть метод, который вызывает [self performSelectorInBackground:...]. И начинается загрузка немного информации из интернета.

После того, как я коснусь кнопки «Домой», затем снова войду в приложение, этот фоновый метод продолжает работать. Так что, если я вызову этот метод снова, у меня будет bad_access, потому что фоновый метод уже работает, и я вызываю его дважды.

Могу ли я прекратить выполнять селектор в фоновом режиме класса A? Например в моем приложении DidEnterBackground? Или я могу проверить, работает ли селектор или что-то еще?

Я нашел пару вещей, как

[[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget:a];
[NSObject cancelPreviousPerformRequestsWithTarget:a selector:@selector(startDownload) object:nil];

Но они не работали для меня. Так

my objAppDelegate:

@inteface ObjAppDelegate
{
     A *a;
}
@implementation ObjAppDelegate
{
    -(void)applicationDidEnterBackground:(UIApplication *)application
    {
        //or it can be didBecomeActive..
        //here. check if background task of class A is running, or just stop it ??
    }
}

@implementation A
{
     //some timer, or event, etc.
     -(void)startDownload
     {
          [self performSelectorInBackground:@selector(runBackgroundTask)           withObject:nil];
      }
    -(void)runBackgroundTask
    {
         //some network stuff..
     }
}

Я сделал это так:

<pre> threadForDownload = [[NSThread alloc] initWithTarget:self selector:@selector(threadMain:) object:nil]; [threadForDownload start]; [self performSelector:@selector(startDownload) onThread:threadForDownload withObject:nil waitUntilDone:NO];</p> <ul> <li><p>(void)threadMain:(id)data { NSAutoreleasePool *pool = [NSAutoreleasePool new];</p> <p>NSRunLoop *runloop = [NSRunLoop currentRunLoop]; [runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];</p> <p>while (YES) { [runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; }</p> <p>[pool release]; }</p></li> </ul> <p>

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

<pre> -(void)startDownload { if (![[UIApplication sharedApplication] isNetworkActivityIndicatorVisible]) // flag.. { //.... } }

// Я делаю видимым networkActivityIndicator каждый раз, когда начинаю скачивать

Ответы [ 4 ]

4 голосов
/ 14 февраля 2011

Вот что нужно сделать:

  1. фоновая задача сохраняет свой поток в свойство где-то, используя NSThread currentThread
  2. фоновая задача периодически проверяет * потока1008 * isCancelled свойство.
  3. основной поток отправляет cancel объекту потока, сохраненному фоновым потоком на шаге 1.
  4. При выходе фоновый поток устанавливает для свойства значение nil.

Все операции над свойством, используемым для хранения потока, должны быть защищены @synchronized или его эквивалентом, чтобы основной поток не отправлял cancel освобожденному объекту потока.

Фоновый поток не может выполнять операции ввода-вывода, которые блокируют в течение более короткого периода времени.В частности, синхронная загрузка URL-адресов с использованием NSURLConnection отсутствует.Если вы используете NSURLConnection, вам нужно перейти к асинхронным методам и циклу выполнения (возможно, в этом случае вы можете вообще отказаться от фонового потока).Если вы используете IOS уровня POSIX, используйте poll() с таймаутом.

4 голосов
/ 14 февраля 2011

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

BOOL isBackgroundTaskRunning;

Затем в runBackgroundTask

if (isBackgroundTaskRunning) {
    // already running
    return;
}
isBackgroundTaskRunning = TRUE;

...

isBackgroundTaskRunning = FALSE;
1 голос
/ 14 февраля 2011

Запустите метод в фоновом потоке и сохраните запись NSThread. Затем, позже, вы можете просто закончить тему.

1 голос
/ 14 февраля 2011

Я не думаю, что было бы спасительно, чтобы вызвать прерывание метода. Что вы можете сделать, это изменить состояние вашего объекта и проверить это состояние внутри реализации вашего метода для досрочного возврата в случае отмены (но не забудьте освободить выделенные объекты).

Так работает NSOperationQueue. Из документации:

Отмена операции не заставляет ее немедленно прекратить то, что она делает. Хотя для всех операций ожидается соблюдение значения, возвращаемого isCancelled, ваш код должен явно проверить значение, возвращаемое этим методом, и при необходимости прервать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...