Comment définir un délai d’attente plus agressif pour HttpWebRequest?

Dans une bibliothèque de classes portable, la méthode suivante consiste à publier des données dans une URL spécifique. La méthode fonctionne très bien. Cependant, j’aimerais spécifier un délai d’attente plus agressif (la valeur par défaut est 100 secondes).

Étant donné qu’il n’existe aucune propriété Timeout sur la classe HttpWebRequest à partir de la bibliothèque de classes portable, comment puis-je m’assurer que l’appel est abandonné s’il prend plus de quelques secondes?

public async Task PostAsync(Uri uri, ssortingng data) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; using (Stream requestStream = await request.GetRequestStreamAsync()) { byte[] postBytes = Encoding.UTF8.GetBytes(data); requestStream.Write(postBytes, 0, postBytes.Length); } HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); return new HttpResponse(response.StatusCode, await new StreamReader(response.GetResponseStream()).ReadToEndAsync()); } 

Le code ci-dessous retournera soit un HttpWebResponse, soit NULL si le délai est écoulé.

 HttpWebResponse response = await TaskWithTimeout(request.GetResponseAsync(), 100); if(response != null) { .... } 

 Task TaskWithTimeout(Task task, int duration) { return Task.Factory.StartNew(() => { bool b = task.Wait(duration); if (b) return (HttpWebResponse)task.Result; return null; }); } 

–MODIFIER–

Créer une méthode d’extension serait encore mieux

 public static class SOExtensions { public static Task WithTimeout(this Task task, int duration) { return Task.Factory.StartNew(() => { bool b = task.Wait(duration); if (b) return task.Result; return default(T); }); } } 

L’utilisation serait:

 var response = (HttpWebResponse)await request.GetResponseAsync().WithTimeout(1000); 

–EDIT 2–

Une autre façon de le faire

 public async static Task WithTimeout(this Task task, int duration) { var retTask = await Task.WhenAny(task, Task.Delay(duration)) .ConfigureAwait(false); if (retTask is Task) return task.Result; return default(T); } 
 // Abort the request if the timer fires. private static void TimeoutCallback(object state, bool timedOut) { if (timedOut) { HttpWebRequest request = state as HttpWebRequest; if (request != null) { request.Abort(); } } } 

Oui, il incombe à l’application cliente de mettre en œuvre son propre mécanisme de délai d’attente. Vous pouvez le faire à partir du code ci-dessus qui définit le délai et utilise la méthode ThreadPool.RegisterWaitForSingleObject. Voir http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.abort.aspx pour plus de détails. Il s’agit essentiellement d’un abandon de GetResponse, BeginGetResponse, EndGetResponse, GetRequestStream, BeginGetRequestStream ou EndGetRequestStream.