Доступ к изменяемым данным из обработчика запросов GCDWebServer

Я получаю случайные сбои в своих обработчиках GCDWebServer, которые обращаются к изменяемым словарям. В GCDWebServer ReadMe говорится, что обработчики «выполняются в произвольных потоках внутри GCD, поэтому особое внимание следует уделять безопасности потоков и повторному входу», и я думаю, что это моя проблема. Существует ли наилучшая практика или рекомендуемый шаблон для доступа к изменяемым свойствам родительского объекта из обработчиков?

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

Вот упрощенная версия моего кода:

@property (nonatomic, strong) NSMutableDictionary *data;
@property (nonatomic, strong) GCDWebServer *webServer;

- (void)setup {
    self.data = [NSMutableDictionary dictionary];
    [self.data setObject:@"1" forKey:@"status"];

    self.webServer = [[GCDWebServer alloc] init];
    [self.webServer addHandlerForMethod:@"GET" path:@"/getStatus.txt" requestClass:[GCDWebServerRequest class] processBlock:^(GCDWebServerRequest *request) {
        return [self handleStatusRequest:request];
    }];
}

- (GCDWebServerDataResponse *)handleStatusRequest:(GCDWebServerRequest *)request {
    NSString *status = [self.data objectForKey:@"status"]; // crash here
    return [GCDWebServerDataResponse responseWithText:status];
}

person arlomedia    schedule 03.06.2016    source источник


Ответы (1)


Изменяете ли вы свой data словарь после его создания? Если так, то это объясняет сбои.

Вы должны предотвратить одновременный доступ к вашему data словарю, используя блокировки. Самый простой способ - через GCD, например.

@property dispatch_queue_t lock;

__block NSString* status;
dispatch_sync(self.lock, ^{
  status = [self.data objectForKey:@"status"];
});

NSString* status = @"Hello";
dispatch_async(self.lock, ^{
  [self.data setObject:status forKey:@"status"];
});  // Use dispatch_sync() or dispatch_async() here depending on your needs
person Pol    schedule 04.06.2016
comment
Кажется, это исправлено. Спасибо! - person arlomedia; 09.07.2016