1

Моя библиотека предоставляет 2 API, по следующим адресам:Принудительный порядок исполнения с использованием dispatch_sync

-(void) createFile{ 

    dispatch_sync(queueSerial, ^{ //B1 

    [fileObj createFileInfo:file completion:^(NSError *error){ 

     //execute completion block C1 
    }]; 

    }); 
} 

-(void) readFile:(NSData*)timeStamp{ 

    dispatch_async(queueSerial, ^{ //B2 

     [fileObj readFileInfo:fileName completion:^(NSError *error) { 
      dispatch_async(queueSerial2, ^{ 

       //execute completion block C2 

      }); 
     }] 

    }); 
} 

Оба readFile и createFile асинхронные методы.

Обычно я рекомендую людям, с помощью моей библиотеки позвонить по телефону createFile до readFile. Тем не менее, нет гарантии, что вызывающие абоненты в конечном итоге смогут это реализовать. Это, как правило, получает вызывается следующим образом (и я не имею никакого контроля над этим)

[fileClass createFile]; 
[fileClass readFile:timeStamp]; 

То, что я хочу сделать, это обеспечить readFile вызывается после того, как completion block C1 выполняется. Я также не хочу блокировать основной поток createFile (но это ожидание можно смягчить). Так что я хочу достичь, как конечный результат:

  1. Caller (что я не имею никакого контроля над) вызывает createFile и сразу после звонков readFile
  2. createFile полностью выполняет, блок завершения C1 увольняют и после что, readFile отправлен, чтобы сделать это.

Как я могу это достичь?

+0

@Rob спасибо за понимание.В настоящий момент я являюсь полным молодым (в Obj C), поэтому я буду стараться следовать вашему предложению впредь. – ExceptionHandler

+0

Как 'readFile' передает данные, которые он читает? Он определен как return 'void', поэтому он должен использовать обработчик завершения или шаблон делегирования? – Rob

+0

@Rob 'readFile' передает данные (значение ошибки, если они есть) в обработчик завершения C2. Я не был уверен, были ли эти части релевантными. – ExceptionHandler

ответ

1

Похоже, вы пытаетесь использовать существующий API-интерфейс, основанный на обработчике завершений, и обучите его в шаблон последовательной очереди. Но серийные очереди имеют смысл только тогда, когда отправленные блоки сами по себе синхронны. (И не путайте это с dispatch_sync ... мы говорим о том, является ли задача внутри блока асинхронной или нет, а не как вы отправили ее в свою очередь.) Но вы имеете дело с асинхронными методами, вызываемыми из других асинхронные методы.

Базовый шаблон при работе с методами, использующими блоки обработчика завершения, заключается в том, чтобы полностью исключить очередность очереди (нет необходимости в очереди GCD или полезно, когда задачи уже асинхронны) и просто использовать блоки обработчика завершения в своих собственных методах , и сделать последний вызов в самом глубоко вложенном блоке, вызовите свой собственный обработчик завершения.

Например:

- (void)foo:(void (^)())completion { 
    [fileObj setFileInfo:file completion:^(NSError *error) { 
     // do some other stuff 
     completion(); 
    }]; 
} 

- (void)bar:(void (^)())completion { 
    [fileObj getFileInfo:fileName completion:^(NSError *error) { 
     // do some other stuff 
     completion(); 
    }]; 
} 

И тогда вы бы назвали это так:

[self foo:^{ 
    [self bar:^{ 
     // do whatever you want when its all done 
    }]; 
}]; 

Это означает, что он не будет делать какие-либо из getFile материала пока setFile материал не будет сделано ,

Сказав это, интересно, какое добавочное значение добавили ваши методы setFile и getFile, помимо собственных методов классов FileObject.

Но ключ заключается в том, что при работе с асинхронными методами вы не можете легко координировать их с помощью простой последовательной очереди GCD. Если вы хотите, чтобы диспетчерская очередность, как поведение для самих задач, была асинхронной, тогда вы, как правило, рассматривали бы вместо этого очереди операций (или обещания/фьючерсы или что-то в этом роде).

+0

Я понимаю, что вы пытаетесь сказать, но дело в том, что я только контролирую методы 'setFile'' getFile' и * not * над тем, как они вызваны к сожалению. Итак, мне нужно обойти ограничения. Лучшее, что я могу сделать, это заставить отправить 'getFileInfo' после завершения 'setFileInfo' – ExceptionHandler

+0

. Затем вы должны отредактировать свой вопрос, как его зовут (и объясните, почему они не могут быть изменены). Но основная истина заключается в том, что вы не можете просто использовать асинхронные методы и добавить их в очередь и ожидать, что очередь обработает это. Теоретически вы можете сделать их синхронными, но это поистине ужасная идея (по многим причинам). Если вы хотите, вы можете сделать эти асинхронные подклассы «NSOperation», но это тоже изменит ваш API (и, в то время как классный, требует больше работы, чтобы делать правильно). Пожалуйста, просто отредактируйте вопрос, связанный с ограничениями, которые у вас есть на вашем API ... – Rob

+0

Насколько это значение добавляет эти методы, они являются единственными методами этого класса «FileObject», который подвергается вызовам клиентов, вызывающим мой процесс. Я не полностью не согласен использовать другие методологии для достижения этой цели. Просто метод 'setFile' вычисляется тяжелым образом и должен выполняться до того, как' getFile' будет вызван с его чувствительным временем 'timeStamp' expires – ExceptionHandler