2013-08-22 12 views
19

Sono incredibilmente nuovo alla programmazione, e ho imparato abbastanza bene finora, penso, ma non riesco ancora a capire l'idea di fare un ritardo nel modo in cui voglio. Quello su cui sto lavorando è una sorta di "gioco" di prova che utilizza un'applicazione di moduli Windows che coinvolge un sistema di combattimento. In esso, voglio creare un NPC che esegua un'azione ogni due secondi. Il problema è che voglio anche consentire al giocatore di interagire tra gli attacchi. Thread.sleep davvero non sembra funzionare per me, non solo perché non so come multithread, ma ogni volta che provo a farlo funzionare, per esempio, in questo modo:Come posso eseguire un breve ritardo in C# senza usare il sonno?

textBox1.Text += "\r\nThread Sleeps!"; 
System.Threading.Thread.Sleep(4000); 
textBox1.Text += "\r\nThread awakens!"; 

Sembra di insistere a dormire prima, quindi stampare entrambe le righe.

Penso che sia tutto quello che posso dire al momento, ma se è ancora troppo vago o prolisso, sentitevi liberi di dirmelo.

In breve, In C# Voglio fare qualcosa in ritardo prima dell'esecuzione, ma allo stesso tempo consentire l'interazione dell'utente.

+1

è possibile utilizzare il timer invece e sparare al tuo intervallo ... – Rohit

+0

Il thread è anche responsabile della stampa dell'interfaccia utente, ma poiché lo si blocca usando 'Sleep' non è possibile aggiornare l'interfaccia utente che mostra la prima linea. – user2674389

+0

Utilizzare Task.Delay anziché Sleep. Quindi non avrai problemi con l'interfaccia utente bloccata. Questa nuova funzione è disponibile in .Net 4.5. – Ohlin

risposta

47

Se si utilizza .NET 4.5, è possibile utilizzare il nuovo framework async/await per interrompere senza bloccare il thread.

Il modo in cui funziona è contrassegnare la funzione che necessita di operazioni asincrone, con la parola chiave async. Questo è solo un suggerimento per il compilatore. Quindi si utilizza la parola chiave await sulla riga in cui si desidera eseguire il codice in modo asincrono e il programma attenderà senza bloccare il thread o l'interfaccia utente. Il metodo che chiami (sulla linea di attesa) deve essere contrassegnato anche con una parola chiave async e di solito viene chiamato termina con Async, come in ImportFilesAsync.

Quello che dovete fare nel tuo esempio è:

  1. Assicurarsi che il programma ha .Net Framework 4.5 come target quadro
  2. Mark la funzione che ha bisogno di dormire con la parola chiave async (vedi esempio sotto)
  3. Aggiungi using System.Threading.Tasks; al tuo codice.

Il codice è ora pronto per l'uso il metodo invece del metodo System.Threading.Thread.SleepTask.Delay (è possibile utilizzare await su Task.Delay perché Task.Delay è contrassegnato con async nella sua definizione).

private async void button1_Click(object sender, EventArgs e) 
    { 
     textBox1.Text += "\r\nThread Sleeps!"; 
     await Task.Delay(3000); 
     textBox1.Text += "\r\nThread awakens!"; 
    } 

Qui potete leggere di più su Task.Delay e Await.

+0

È corretto che tutto il codice dopo "await" verrà eseguito in modo asincrono? Ho fatto un esempio con due checkbox e sembra che sia il caso. – Black

+0

@Black Puoi usare solo 'await' su una funzione che è contrassegnata come' async', quindi sì - sarà sempre asincrona. – Ohlin

+0

ma solo la parte dopo l'attesa? – Black

4

Siamo spiacenti per il risveglio di una vecchia domanda come questa. Ma penso che l'autore originale volesse una risposta:

È necessario forzare il programma a eseguire l'aggiornamento grafico dopo aver apportato la modifica alla casella di testo1.Potete farlo invocando Update();

textBox1.Text += "\r\nThread Sleeps!"; 
textBox1.Update(); 
System.Threading.Thread.Sleep(4000); 
textBox1.Text += "\r\nThread awakens!"; 
textBox1.Update(); 

Normalmente questo sarà fatto automaticamente quando il thread è fatto. Es, si preme un pulsante, le modifiche vengono apportate al testo, i fili muore, quindi viene generato .Update() e vengono visualizzate le modifiche. (Non sono un esperto quindi non posso dirti quando è stato licenziato, ma è qualcosa di simile a questo in qualsiasi modo.)

In questo caso, si modifica, si interrompe il thread e quindi si modifica il testo di nuovo, e quando il filo muore alla fine viene sparato il .Update(). Questo ti porta a vedere solo l'ultima modifica apportata al testo.

Si verificherebbe lo stesso problema se si eseguisse una lunga esecuzione tra le modifiche del testo.

0
private void WaitNSeconds(int seconds) 
{ 
    if (seconds < 1) return; 
    DateTime _desired = DateTime.Now.AddSeconds(seconds); 
    while (DateTime.Now < _desired) { 
     Thread.Sleep(1); 
     System.Windows.Forms.Application.DoEvents(); 
    } 
} 
0

Aggiungendo using System.Timers; al vostro programma è possibile utilizzare questa funzione:

private static void delay(int Time_delay) 
{ 
    int i=0; 
    // ameTir = new System.Timers.Timer(); 
    _delayTimer = new System.Timers.Timer(); 
    _delayTimer.Interval = Time_delay; 
    _delayTimer.AutoReset = false; //so that it only calls the method once 
    _delayTimer.Elapsed += (s, args) => i = 1; 
    _delayTimer.Start(); 
    while (i == 0) { }; 
} 

Delay è una funzione e può essere utilizzato come:

delay(5000);