Délai d’attente de la tâche async

J’ai ce morceau de code pour faire une requête HTTP asynchrone:

public static void MakeRequest(Uri uri, Action responseCallback) { WebRequest request = WebRequest.Create(uri); request.Proxy = null; Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null).ContinueWith(task => { WebResponse response = task.Result; Stream responseStream = response.GetResponseStream(); responseCallback(new RequestCallbackState(response.GetResponseStream())); responseStream.Close(); response.Close(); }); } 

Cela fonctionne, mais je dois définir un délai d’expiration de la demande. J’ai essayé d’utiliser request.Timeout mais ne semble rien faire. Existe-t-il un moyen de définir un délai d’expiration de tâche dans ce code?

Modifié pour append un nouveau rappel de délai d’attente. Nouveau code:

  public static void MakeRequest(Uri uri, Action responseCallback) { WebRequest request = WebRequest.Create(uri); request.Proxy = null; IAsyncResult t = Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null).ContinueWith(task => { WebResponse response = task.Result; Stream responseStream = response.GetResponseStream(); responseCallback(new RequestCallbackState(response.GetResponseStream())); responseStream.Close(); response.Close(); }); ThreadPool.RegisterWaitForSingleObject(t.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, 1000, true); } private static void TimeoutCallback(object state, bool timedOut) { if (timedOut) { Console.WriteLine("Timeout"); WebRequest request = (WebRequest)state; if (state != null) { request.Abort(); } } } 

Test avec:

 HttpSocket.MakeRequest(new Uri("http://www.google.comhklhlñ"), callbackState => { if (callbackState.Exception != null) throw callbackState.Exception; Console.WriteLine(GetResponseText(callbackState.ResponseStream)); }); Thread.Sleep(10000); 

De la documentation Timeout :

La propriété Timeout n’a aucun effet sur les demandes asynchrones effectuées avec la méthode BeginGetResponse ou BeginGetRequestStream.

En effet, le cadre vous oblige à gérer vous-même le délai d’attente. Vous devriez pouvoir utiliser l’ exemple de code ici , sauf transmettre la Task renvoyée de l’appel FromAsync à la méthode ThreadPool.RegisterWaitForSingleObject .


Modifier:

Vous devez mettre l’enregistrement sur la tâche d’origine, pas la suite:

 public static void MakeRequest(Uri uri, Action responseCallback) { WebRequest request = WebRequest.Create(uri); request.Proxy = null; const int TimeoutPeriod = 1000; Task t = Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null); ThreadPool.RegisterWaitForSingleObject((t as IAsyncResult).AsyncWaitHandle, TimeoutCallback, request, TimeoutPeriod, true); t.ContinueWith(task => { WebResponse response = task.Result; Stream responseStream = response.GetResponseStream(); responseCallback(response.GetResponseStream()); responseStream.Close(); response.Close(); }); } 

Cela fonctionne pour moi (si je règle la durée du délai d’attente très rapidement et que je clique dessus, j’ai toujours le délai d’expiration de manière appropriée).