2013-08-29 19 views
5

Il metodo di chiamata originale è simile:timeout una chiamata di metodo

public string AskAPI(string uri) 
{ 
    return api.Query(uri); 
} 

in cui l'API è semplicemente un riferimento dll importato.

In questo momento desidero aggiungere una funzione di timeout al metodo AskAPI, in modo che se api.Query impiega più tempo di, diciamo 30 secondi, AskAPI genererà un'eccezione.

Sembra che non sarò in grado di farlo funzionare. Qualcuno può condividere le loro opinioni su questo?

Grazie!

+0

Dovresti essere in grado di modificare 'api.Query' per aggiungere la funzionalità di timeout. Dato che non hai fornito informazioni su ciò che è, è impossibile dirti come farlo. (Non c'è modo di timeout per la chiamata, in quanto non hai modo di interromperlo in base a ciò che hai postato qui.) –

+0

@KenWhite api.Query non è nemmeno nel mio controllo. Vuoi dire senza modificarlo, non posso far scadere il metodo AskAPI? – jamesdeath123

+0

Non posso rispondere, perché hai fornito esattamente tre righe di codice ('{}' non conta) totalmente fuori dal contesto, con assolutamente nessun'altra informazione. Sulla base di ciò che hai pubblicato, la risposta sarebbe "No, non puoi". –

risposta

8

Si potrebbe utilizzare Tasks per fare questo, ecco un esempio:

public string AskAPI(string uri, int millis) 
{ 
    using (var task = new Task<string>(() => api.Query(uri))) 
    { 
     task.Start(); 
     task.Wait(millis); 
     if (!task.IsCompleted) throw new TimeoutException(); 
     return task.Result; 
    } 
} 

Grazie a Guillaume per il suggerimento di usare un TimeoutException.

Ma come sottolinea Jim Mischel, questo non impedirà il completamento dell'attività, nel qual caso sarebbe meglio se fosse possibile modificare l'API che si sta chiamando, perché in tal caso si potrebbe fare pieno uso della classe CancellazioneToken che è stato creato per questo genere di cose.

Oltre a questo, l'unica altra soluzione rapida che posso pensare (che può essere sconsigliabile) sarebbe quella di avvolgere il metodo (o combinarlo) con qualcosa di simile:

public T Await<T>(Func<T> fun, int millis) 
{ 
    using (var cancel = new CancellationTokenSource(millis)) 
    using (var task = new Task<T>(() => 
    { 
     T result = default(T); 
     var thread = new Thread(() => result = fun()); 
     thread.Start(); 
     while (!cancel.Token.IsCancellationRequested && thread.IsAlive) ; // Wait for a sign from above 
     thread.Abort(); 
     cancel.Token.ThrowIfCancellationRequested(); 
     return result; 
    }, cancel.Token)) 
    { 
     task.Start(); 
     task.Wait(millis); 
     cancel.Cancel(); 
     if (!task.IsCompleted) throw new TimeoutException(); 
     return task.Result; 
    } 
} 

E poi chiamare utilizzando:

Await(() => AskAPI("http://some.uri"), 30000); 
+1

Non lanciare 'Eccezione'. Lancia 'TimeoutException'. – Guillaume

+1

@Guillaume Grazie per quello, avrei dovuto prendermi il tempo per dare un'occhiata. =) – sgbj

+2

Ma l'attività continua a essere eseguita, giusto? Cioè, 'api.Query' non viene annullato? –

Problemi correlati