2014-01-08 4 views
1

Я пытаюсь реализовать параллелизм в objective C. У меня есть проблема с действиями, которые нужно запускать синхронизированным образом. Проблема здесь в том, что я использую функцию, которая выполняет блок после завершения.Обработка параллелизма и асинхронный ответ

Я хочу подключиться к устройству Bluetooth для выполнения некоторых операций и подключения к следующему устройству.

for (Beacon * beacon in beacons) { 
    [beacon setDelegate:self]; 
    [beacon connectToBeacon]; 
} 

Но соединение является асинхронным. Маяк вызовет метод делегирования (в этом случае это тот же класс) didConnectSuccess, когда соединение выполнено успешно.

Мне нужно подождать все мои операции в «beaconDidConnect» и разблокировать, чтобы завершить работу перед подключением к следующему устройству.

Я сейчас использую комбинацию очереди отправки и отправки семафор, мой семафор является Ивар

dispatch_queue_t myCustomQueue; 
myCustomQueue = dispatch_queue_create("com.example.MyCustomQueue", NULL); 

for (Beacon * beacon in beacons) { 
    [beacon setDelegate:self]; 
    dispatch_async(myCustomQueue, ^{ 
     dispatch_semaphore_wait(semaphoreBluetooth, DISPATCH_TIME_FOREVER); 
     [beacon connectToBeacon]; 

    }); 
} 

В сочетании с

- (void)beaconDidDisconnect:(Beacon *)beacon 
{ 
    dispatch_semaphore_signal(semaphoreBluetooth); 
} 

Без dispatch_async, путем блокирования обратного вызова (beaconDidConnect), ожидание вызывало тупик. Я хотел dispatch_semaphore_wait в цикле for, а не в блоке отправки, но ожидание вызывает повторный вызов, что вызывает тупик.

Этот способ, кажется, работает, но я нашел его немного уродливым.

Моя другая проблема заключается в том, что в моем методе beaconDidConnect мне нужно связать asynchronous звонок и в каждом ожидании предыдущего для завершения.

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

Мне нужен эквивалент концепции «обещание» javascript.

В настоящее время у меня есть что-то с диспетчерской очередью и отправкой семафора, но иногда я имею тупик по неизвестной причине.

Например:

- (void)beaconConnectionDidSucceeded:(Beacon *)beacon 
{ 
    dispatch_semaphore_t semaphoreEditing = dispatch_semaphore_create(1); 
    dispatch_queue_t editingQueue = dispatch_queue_create("com.example.MyCustomQueue.Editing", NULL); 

    // First writing procedure 
    dispatch_async(editingQueue, ^{ 
     dispatch_semaphore_wait(semaphoreEditing, DISPATCH_TIME_FOREVER); 
     [beacon writeSomeCaracteristic:caracteristic withValue:value withCompletion:^(void) { 
      dispatch_semaphore_signal(semaphoreEditing); 
     }]; 
    }); 

    // A unknow number of writing sequences 
    dispatch_async(editingQueue, ^{ 
     dispatch_semaphore_wait(semaphoreEditing, DISPATCH_TIME_FOREVER); 
     [beacon writeSomeCaracteristic:caracteristic withValue:value withCompletion:^(void) { 
      dispatch_semaphore_signal(semaphoreEditing); 
     }]; 
    }); 
    // 
    // ... 
    // 
    dispatch_async(editingQueue, ^{ 
     dispatch_semaphore_wait(semaphoreEditing, DISPATCH_TIME_FOREVER); 
     [beacon writeSomeCaracteristic:caracteristic withValue:value withCompletion:^(void) { 
      dispatch_semaphore_signal(semaphoreEditing); 
     }]; 
    });  

    // Terminate the edition 
    dispatch_async(editingQueue, ^{ 
     dispatch_semaphore_wait(semaphoreEditing, DISPATCH_TIME_FOREVER); 
     [beacon disconnectBeacon]; 
     dispatch_semaphore_signal(semaphoreEditing); 
    }); 
} 

Я хочу написать ясный код, выполнять мои инструкции в последовательном пути.

ответ

0

Я хранил dispatch_queue и dispatch_semaphore для связи, но для операций записи я использую библиотеку под названием Sequencer. Я нашел here.

Это принцип Promises, о котором говорил CouchDeveloper.

0

Считаете ли вы использование NSOperation и NSOperationQueue?

Если вам нужно дождаться, когда каждый маяк выполнит набор операций перед продолжением, вы можете сохранить каждый набор операций в NSOperation и поместить все операции внутри NSOperationQueue с maxConcurrentLimit из 1. Возможно, было бы проще отменить/приостановить/прекратить каждую операцию, и очередь будет поддерживать параллелизм.

2

Если асинхронные методы есть обработчик завершения, вы можете «упорядочивание» или «цепь» ряд асинхронных вызовов, как показано ниже:

[self asyncFooWithCompletion:^(id result){ 
    if (result) { 
     [self asyncBarWithCompletion:^(id result){ 
      if (result) { 
       [self asyncFoobarWithCompletion:^(id result){ 
        if (result) { 
         ... 
        } 
       }]; 
      } 
     }]; 
    } 
}]; 

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

С библиотекой третьей стороны, которая особенно помогает преодолеть эти проблемы (включая обработку ошибок, отмена) может выглядеть примерно так, как код ниже:

Дано:

- (Promise*) asyncFoo; 
- (Promise*) asyncBar; 
- (Promise*) asyncFoobar; 

«СЦЕПЛЕНИЕ» троих асинхронные методы, включая обработку ошибок:

[self asyncFoo] 
.then(^id(id result){ 
    ... // do something with result of asyncFoo 
    return [self asyncBar]; 
}, nil) 
.then(^id (id result){ 
    ... // do something with result of asyncBar 
    return [self asyncFoobar]; 
}, nil) 
.then(^id(id result) { 
    ... // do something with result of asyncFoobar 
    return nil; 
}, 
^id(NSError*error){ 
    // "catch" any error from any async method above 
    NSLog(@"Error: %@", error); 
    return nil; 
}); 

Для общей информации о «Promises», пожалуйста, прочитайте статью вики Futures and Promises.

Существует множество библиотек Objective-C, которые реализуют Promise.

+0

Я думал об этом решении, но я думал, что в ObjectiveC есть более идиоматический способ сделать это. Спасибо! – luxcem

+1

Я думаю, что это «идиоматический»;) К сожалению, Objective-C не имеет встроенных функций для выражения асинхронного стиля программирования, такого как ключевое слово «async» или «yield», как на других языках. – CouchDeveloper

Смежные вопросы