2011-12-18 6 views
12

Come posso eseguire periodicamente il blocco di codice in background usando GCD? Sto provando a scrivere un motore di gioco con diversi sottosistemi, come il rendering, la fisica, la logica di gioco e così via. Alcune attività dovrebbero essere guidate dagli eventi, ma alcune (come il sistema di fisica) dovrebbero essere periodicamente chiamate in background con un tempo costante (ad esempio dopo 1/100 di secondo). Ho creato un blocco di codice, ma come posso eseguire periodicamente questo blocco in background? Lo strumento giusto per GCD è qui?Come posso eseguire periodicamente il blocco di codice in background usando GCD?

risposta

6

Come note @matt nei commenti, è possibile utilizzare le origini di invio timer per questo. Vedi la sua risposta per il giusto approccio lì.

Ai posteri, ecco la mia risposta originale con alcune alternative:

  1. Nella tua callback render (ad esempio, utilizzando CADisplayLink), sparare un lavoro GCD che calcola la fisica di questo (o il prossimo?) telaio. Se è necessario eseguire più di un aggiornamento per frame di rendering, è sufficiente ripetere il ciclo di lavoro un paio di volte.

  2. Avere un thread di fisica che dorme da solo fino a quando non è necessario eseguire alcuni calcoli. Se si dispone di un thread separato per questo, NSTimer potrebbe avere una risoluzione sufficiente per riattivare il thread a 100 Hz. (Sul thread principale, questo non funzionerebbe perché altre sorgenti di input sul runloop gli impediranno di sparare così velocemente in modo coerente.) Se NSTimer non funziona, basta calcolare quanto tempo è rimasto fino al prossimo aggiornamento di fisica di cui hai bisogno e sleep your thread (tramite, ad esempio, [NSThread sleepForTimeInterval:])

  3. Avere un blocco che utilizza dispatch_after.

Qualcosa di simile a questo:

dispatch_time_t next = dispatch_time(DISPATCH_TIME_NOW, 0); 
block = ^{ 
    next = dispatch_time(next, 10000000L); // increment by 10 ms 
    // do physics here 
    dispatch_after(next, queue, block); 
} 

potresti aver bisogno di essere un po 'più intelligente perdite di fotogrammi, (cioè di rilevare se la vostra prossima volta è nel passato prima di chiamare dispatch_after esso, ecc)

+0

Ciao, grazie per la risposta. Il mio obiettivo principale è disaccoppiare il sottosistema di fisica dal rendering, quindi penso che la seconda risposta sia più adatta a me, tuttavia mi sto ancora chiedendo se ci siano soluzioni con blocchi e GCD. – asdf

+0

OK. Ho aggiunto una terza opzione. –

+1

"Le origini di invio del timer generano eventi a intervalli regolari basati sul tempo.È possibile utilizzare i timer per avviare attività specifiche che devono essere eseguite regolarmente.Ad esempio, i giochi e altre applicazioni ad uso intensivo della grafica potrebbero utilizzare i timer per avviare aggiornamenti di schermate o animazioni. " Se questo non è GCD che supporta attività periodiche direttamente - e esattamente nel contesto in cui l'OP sta chiedendo - che cos'è? – matt

3

In Swift è possibile creare timer utilizzando GCD:

func CreateTimerDispatchSource(interval: UInt64, leeway: UInt64, queue: dispatch_queue_t, block: dispatch_block_t) -> dispatch_source_t { 
    let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue) 
    dispatch_source_set_timer(timer, dispatch_walltime(nil, 0), interval, leeway) 
    dispatch_source_set_event_handler(timer, block) 
    return timer; 
} 

var timer = CreateTimerDispatchSource(5*NSEC_PER_SEC, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 
    // do some serious stuff 
} 

di avviare o riprendere il timer:

dispatch_resume(timer) 

Sospendi Timer:

dispatch_suspend(timer) 
Problemi correlati