2013-10-31 14 views
26

Domanda rapida, voglio aspettare un secondo prima di lanciare un compito asincrona senza un valore di ritorno.
È questo il modo giusto per farlo?ritardo quindi eseguire Task

Task.Delay(1000) 
    .ContinueWith(t => _mq.Send(message)) 
    .Start(); 

Cosa succede alle eccezioni?

+0

Perché stai utilizzando il CTP asincrono? La versione finale è stata fuori per molto tempo. E se puoi usare un metodo asincrono, non devi usare ContinueWith manualmente - attendi il ritardo.Potresti dare più contesto per favore? –

+1

sì, è il modo migliore. per la gestione delle eccezioni: http://stackoverflow.com/questions/12980712/what-is-the-best-way-to-catch-exception-in-task http://stackoverflow.com/questions/5983779/catch-exception-that-is-thrown-in-different-thread – Nahum

+0

@jon: tag errato :) viene utilizzato all'interno di un servizio Windows. – David

risposta

28

Prima di tutto, Start() funziona solo sugli (molto rari) Task s creati con il costruttore Task (ad esempio new Task(() => _mq.Send(message))). In tutti gli altri casi, verrà generata un'eccezione, poiché Task è già stato avviato o in attesa di un altro Task.

Ora, probabilmente il modo migliore per farlo sarebbe quello di mettere il codice in un metodo separato async e utilizzare await:

async Task SendWithDelay(Message message) 
{ 
    await Task.Delay(1000); 
    _mq.Send(message); 
} 

Se fate questo, ogni eccezione dal metodo Send() finirà in il reso Task.

Se non si desidera farlo, utilizzare ContinueWith() è un approccio ragionevole. In tal caso, l'eccezione sarebbe nel Task restituita da ContinueWith().

Inoltre, a seconda del tipo di _mq, considerare l'utilizzo di SendAsync(), se è disponibile qualcosa di simile.

0

È possibile osservare eventuali eccezioni se si dispone di Wait per l'attività.

eccezioni

Unhandled che vengono gettati dal codice utente che esegue un task vengono propagate al thread giunzione, tranne in alcuni scenari descritti più avanti in questo argomento. Le eccezioni vengono propagate quando si utilizza uno dei metodi Task.Wait o Task.Wait statici o di istanza e vengono gestiti includendo la chiamata in un'istruzione try-catch.

Estratto dal Exception Handling (Task Parallel Library)

attenzione con temporizzazioni. Le attività utilizzano uno scheduler e non sono garantite per iniziare quando si dice "vai". Il codice garantirà almeno ritardo di 1000 ms dopo averlo detto a Start ma non è garantito essere 1000ms esattamente.

6

si può prendere qualsiasi eccezione gettato la Task se si attende per il compito di finire:

essere consapevoli di questo tuo Eccezione gettata nel Task sarà quella interna

class Program 
{ 
    static void Main(string[] args) 
    { 
     try 
     { 
      Task task = Task.Delay(1000) 
       .ContinueWith(t => Program.throwsException()); 

      task.Wait();  
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("Exception:" + ex.Message); // Outputs: Exception:One or more errors occurred. 
      Console.WriteLine("Inner exception:" + ex.InnerException.Message); // Outputs: Exception:thrown 
     } 
     Console.ReadKey(); 

    } 
    static void throwsException() 
    { 
     Console.WriteLine("Method started"); 
     throw new Exception("thrown"); 
    } 
}