2012-11-05 12 views
5

In ruby, è possibile causare la sospensione di un thread da un thread in esecuzione simultaneo diverso.Ruby Pausa thread

Di seguito è riportato il codice che ho scritto finora. Voglio che l'utente sia in grado di digitare 'pause thread' e il thread sample500 per mettere in pausa.

#!/usr/bin/env ruby 

# Creates a new thread executes the block every intervalSec for durationSec. 
def DoEvery(thread, intervalSec, durationSec) 
    thread = Thread.new do 
     start = Time.now 

     timeTakenToComplete = 0 
     loopCounter = 0 
     while(timeTakenToComplete < durationSec && loopCounter += 1) 

      yield 

      finish = Time.now 

      timeTakenToComplete = finish - start 

      sleep(intervalSec*loopCounter - timeTakenToComplete)  
     end 
    end 
end 

# User input loop. 
exit = nil 
while(!exit) 
    userInput = gets 
    case userInput 
    when "start thread\n" 
     sample500 = Thread 
     beginTime = Time.now 
     DoEvery(sample500, 0.5, 30) {File.open('abc', 'a') {|file| file.write("a\n")}} 
    when "pause thread\n" 
     sample500.stop 
    when "resume thread" 
     sample500.run 
    when "exit\n" 
     exit = TRUE 
    end 
end 
+1

"Sono nuovo di Ruby, lo sto imparando solo da pochi giorni" - e sei già impegnato? È impressionante! –

+0

Haha grazie! Sembra un linguaggio davvero carino; Adoro l'intera cosa dei blocchi e la resa! –

risposta

3

Passando oggetto thread come argomento di DoEvery funzione non ha senso perché si sovrascrive immediatamente con Thread.new, prova anche questa versione modificata:

def DoEvery(intervalSec, durationSec) 
    thread = Thread.new do 
     start = Time.now 
     Thread.current["stop"] = false 

     timeTakenToComplete = 0 
     loopCounter = 0 
     while(timeTakenToComplete < durationSec && loopCounter += 1) 
      if Thread.current["stop"] 
       Thread.current["stop"] = false 
       puts "paused" 
       Thread.stop 
      end 

      yield 

      finish = Time.now 

      timeTakenToComplete = finish - start 

      sleep(intervalSec*loopCounter - timeTakenToComplete) 

     end 
    end 
    thread 
end 

# User input loop. 
exit = nil 
while(!exit) 
    userInput = gets 
    case userInput 
    when "start thread\n" 
     sample500 = DoEvery(0.5, 30) {File.open('abc', 'a') {|file| file.write("a\n")} } 
    when "pause thread\n" 
     sample500["stop"] = true 
    when "resume thread\n" 
     sample500.run 
    when "exit\n" 
     exit = TRUE 
    end 
end 

Qui DoEvery restituisce un nuovo oggetto thread. Si noti inoltre che Thread.stop ha chiamato all'interno del thread in esecuzione, non è possibile interrompere direttamente un thread da un altro perché non è sicuro.

+0

Grazie per la risposta. Mi piace come la tua soluzione. Ci sono stati alcuni problemi di temporizzazione con esso che ho suggerito in una modifica (solo per rendere la risposta completa per chiunque altro possa incontrarla). Grazie ancora! –

2

Si può essere in grado di meglio in grado di compiere ciò che si sta tentando con Ruby Fiber oggetto, e probabilmente ottenere una migliore efficienza del sistema in esecuzione.

Le fibre sono primitive per l'attuazione della cooperativa leggera in Ruby. Fondamentalmente sono un mezzo per creare blocchi di codice che possono essere messi in pausa e ripresi, proprio come i thread. La differenza principale è che non vengono mai preventivati ​​e che la pianificazione deve essere eseguita dal programmatore e non dalla VM.

Tenendo presente l'attuale implementazione della RM Rubino non offre alcun discussioni in esecuzione simultanei e la migliore si è in grado di realizzare è un programma green threaded, il seguente è un bell'esempio:

require "fiber" 

f1 = Fiber.new { |f2| f2.resume Fiber.current; while true; puts "A"; f2.transfer; end } 
f2 = Fiber.new { |f1| f1.transfer; while true; puts "B"; f1.transfer; end } 

f1.resume f2 # => 
    # A 
    # B 
    # A 
    # B 
    # . 
    # . 
    # . 
Problemi correlati