Безопасны ли большие центральные диспетчерские блоки?

У меня есть класс TestView с переменной экземпляра «loader» типа Loader. Я создал метод в TestView для создания экземпляра загрузчика; и затем начните загружать что-то через 2 секунды.

Этот метод выглядит так:

-(void) createLoaderAndStartLoadingTwoSecondsLater{
loader =  Loader();
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
printf("DISPATCHING AFTER %i seconds", i);
loader->load(*urlRequest);
});
}

В другом месте есть метод dealloc:

-(void) dealloc
{
delete loader;
}

До тех пор, пока не истечет 2-секундный таймер, возможно, что Deloloc будет вызван. В этом случае мне бы хотелось, чтобы блок dispatch_after никогда не выполнялся.

РЕДАКТИРОВАТЬ:
Я хотел бы сделать это:

  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
printf("DISPATCHING AFTER %i seconds", i);
if ( !hasBeenDeleted( loader ) ){
loader->load(*urlRequest);
}
});

Но меня волнуют две вещи:

  • Я не знаю, как бы я реализовал удаленную функцию
  • Я беспокоюсь, что hasBeenDeleted вернет false, а затем загрузчик будет удален в другом потоке.

Поэтому я бы очень хотел сделать это:

  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
printf("DISPATCHING AFTER %i seconds", i);
lockTheOtherThreads();
if ( !hasBeenDeleted( loader ) ){
loader->load(*urlRequest);
}
unlockTheOtherThreads();
});

Но я также не знаю, как реализовать lockTheOtherThreads ()

0

Решение

при условии, что у вас есть это

@implementation MyClass {
Loader *loader;
}

-(void)createLoaderAndStartLoadingTwoSecondsLater{
loader = new Loader();
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
printf("DISPATCHING AFTER %i seconds", i);
loader->load(*urlRequest);
//self->loader->load(*self->urlRequest);
});
}

Созданный вами блок отправки будет содержать сильную ссылку на self, что значит dealloc не будет вызван до выполнения блока.

Также используйте unique_ptr так что вам не нужно звонить удалить. Или же shared_ptr с atomic_load если загрузчик может быть доступен для нескольких потоков.

@implementation MyClass {
std::unique_ptr<Loader> loader;
}

-(void)createLoaderAndStartLoadingTwoSecondsLater{
loader.reset(new Loader()); // will delete previous loader if it exist
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
printf("DISPATCHING AFTER %i seconds", i);
loader->load(*urlRequest);
});
}

// you don't need dealloc anymore

Обновить:

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

-(void)createLoaderAndStartLoadingTwoSecondsLater{
loader.reset(new Loader()); // will delete previous loader if it exist
__weak typeof(self) weakSelf = self; // a weak reference to self
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
typeof(weakSelf) strongSelf = weakSelf;
printf("DISPATCHING AFTER %i seconds", i);
if (strongSelf) { // if still alive
strongSelf->loader->load(*urlRequest);
} // else it is deallocated
});
}
3

Другие решения

Совершенно неясно, что вы на самом деле пытаетесь сделать. И вещи не просто «потокобезопасны», вам нужно сказать, что вы хотите сделать.

После вызова dealloc рассматриваемый объект исчезнет, ​​когда dealloc вернется. Не имеет значения, если кто-то еще пытался его сохранить. И кажется, что вы смешиваете Objective-C и C ++. Когда в C ++ вызывается delete, объект исчезает.

Я предлагаю вам прочитать слабые указатели в Objective-C и держаться подальше от C ++.

0

По вопросам рекламы [email protected]