2015-09-08 3 views
1

Недавно у меня возникла проблема с использованием GCD. Вот некоторые фрагменты кода:GCD добавить блок в последовательную очередь после изменения состояния

static dispatch_queue_t queue() { 
    static dispatch_queue_t sl_queue; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     sl_queue = dispatch_queue_create("com.somnus.xxx", NULL); 
    }); 

    return sl_queue; 
} 

- (void)test 
{ 
     while (self.state != finished) 
     { 
      //wait for finish 
     } 

     dispatch_async(queue(), ^{ 

       self.state = processing; 


      void (^onFinish)(void) = 0; 
      onFinish = ^(void){ 
       self.state = finished; 
      }; 

      [someObj doSomethingWithFinishBlock:onFinish]; 

     }); 
} 

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

Как я мог реализовать это, спасибо за любую помощь!

EDIT:

doSomethingWithFinishBlock является асинхронная функция, я не знаю, когда onFinish блок будет помещён

+0

Асинхронная функция 'doSomethingWithFinishBlock'? –

+0

@ Cy-4AH Да, doSomethingWithFinishBlock - это асинхронная функция – SomnusLee

ответ

0

Вы должны использовать DISPATCH_QUEUE_SERIAL в вашем dispatch_queue_create ("com.somnus.xxx", NULL) ;

Тогда вам не придется делать

while (self.state != finished) 
    { 
     //wait for finish 
    } 

как блоки помещён и выполнить одну за другой.

Блоки существуют, поэтому вам не нужно активно ждать. Тогда вам не нужно иметь переменную состояния.

Все это было бы просто:

static dispatch_queue_t queue() { 
    static dispatch_queue_t sl_queue; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     sl_queue = dispatch_queue_create("com.somnus.xxx", DISPATCH_QUEUE_SERIAL); 
    }); 

    return sl_queue; 
} 

- (void)test 
{ 
    dispatch_async(queue(), ^{ 
     [someObj doSomethingWithFinishBlock:nil]; 
    }); 
} 
+0

«Вы должны использовать DISPATCH_QUEUE_SERIAL в своем dispatch_queue_create (« com.somnus.xxx », NULL);» 'DISPATCH_QUEUE_SERIAL' определяется как' NULL' – newacct

+0

@Alistra, я хочу убедиться, что блок onFinish установлен в очередь перед следующим [someObj doSomethingWithFinishBlock: nil] блоком. – SomnusLee

+0

@newacct читаемость кода важна, никто не знает, что означает NULL сразу без документов. – Alistra

2

Это обычно делается с dispatch_semaphore. Что-то в этих строках:

@property (nonatomic, readwrite, strong) dispatch_semaphore_t sem; 

// ... At some point you must initialize it to 1 
// this essentially creates a pool of 1 token to share. 
self.sem = dispatch_semaphore_create(1); 

- (void)test 
{ 
    // Checkout a token from the pool (there's only one) 
    // block until I can get get. You could also timeout, which can be useful. 
    dispatch_semphore_wait(self.sem, DISPATCH_TIME_FOREVER); 

    // Do a weak-self dance here if you need one. You may not in your example. 
    dispatch_async(queue(), ^{ 
     dispatch_block_t onFinish = ^{ 
      // Return the token to the pool 
      dispatch_semaphore_signal(self.sem) 
     }; 

     [someObj doSomethingWithFinishBlock:onFinish]; 
    }); 
} 
Смежные вопросы