2014-01-21 100 views
1

昨天我已經found out如何在沒有異步/等待的情況下創建多個異步http請求。但是今天我需要在循環中完成它:如果某些響應不滿足某些條件 - 我需要爲它們更改請求並再次發送這些請求。它可能會重複多次。 我試過這段代碼:如何在循環中創建異步http請求?

do 
{ 
    var loadingCoordinatesTasks = new List<Task<Terminal>>(); 
    var totalCountOfTerminals = terminalPresetNode.ChildNodes.Count; 
    var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 

    foreach (var terminal in terminals.Except(_terminalsWithCoordinates)) 
    { 
     var address = terminal.GetNextAddress(); 
     var webRequest = (HttpWebRequest)WebRequest.Create(GeoCoder.GeoCodeUrl + address); 
     var webRequestTask = Task.Factory.FromAsync<WebResponse>(webRequest.BeginGetResponse, 
                   webRequest.EndGetResponse, 
                   terminal); 
     var parsingTask = webRequestTask.ContinueWith(antecedent => 
     { 
      // Parse the response 
     }); 
     loadingCoordinatesTasks.Add(parsingTask); 
    } 

    Task.Factory.ContinueWhenAll(loadingCoordinatesTasks.ToArray(), antecedents => 
    { 
     foreach (var antecedent in antecedents) 
     { 
      var terminalWithCoordinates = antecedent.Result; 
      if (antecedent.Status == TaskStatus.RanToCompletion && 
       !terminalWithCoordinates.Coordinates.AreUnknown) 
      { 
       _terminalsWithCoordinates.Add(terminalWithCoordinates); 
       _countOfProcessedTerminals++; 
      } 
     } 
    }); 
} while (_countOfProcessedTerminals < totalCountOfTerminals); 

,但它可以檢查在while只是條件後執行的每一個組請求?

回答

0

我管理使用遞歸做到這一點:

public void RunAgainFailedTasks(IEnumerable<Task<Terminal>> tasks) 
    { 
     Task.Factory.ContinueWhenAll(tasks.ToArray(), antecedents => 
     { 
      var failedTasks = new List<Task<Terminal>>(); 
      foreach (var antecedent in antecedents) 
      { 
       var terminal = antecedent.Result; 
       // Previous request was failed 
       if (terminal.Coordinates.AreUnknown) 
       { 
        string address; 
        try 
        { 
         address = terminal.GetNextAddress(); 
        } 
        catch (FormatException) // No versions more 
        { 
         continue; 
        } 
        var getCoordinatesTask = CreateGetCoordinatesTask(terminal, address); 
        failedTasks.Add(getCoordinatesTask); 
       } 
       else 
       { 
        _terminalsWithCoordinates.Add(terminal); 
       } 
      } 
      if (failedTasks.Any()) 
      { 
       RunAgainFailedTasks(failedTasks); 
      } 
      else 
      { 
       // Display a map 
      } 
    }, CancellationToken.None, 
     TaskContinuationOptions.None, 
     TaskScheduler.FromCurrentSynchronizationContext()); 
} 

private Task<Terminal> CreateGetCoordinatesTask(Terminal terminal, string address) 
    { 
     var webRequest = (HttpWebRequest)WebRequest.Create(GeoCoder.GeoCodeUrl + address); 
     webRequest.KeepAlive = false; 
     webRequest.ProtocolVersion = HttpVersion.Version10; 
     var webRequestTask = Task.Factory.FromAsync<WebResponse>(webRequest.BeginGetResponse, 
                   webRequest.EndGetResponse, 
                   terminal); 
     var parsingTask = webRequestTask.ContinueWith(webReqTask => 
     { 
      // Parse the response 
     }); 
     return parsingTask; 
    } 
0

你可以增加數後進行檢查:

_countOfProcessedTerminals++; 
if (_countOfProcessedTerminals >= totalCountOfTerminals) 
{ 
    break; 
} 

_countOfProcessedTerminals線程安全的,但?

+0

謝謝!看看我的編輯 – Zharro

+0

不,它不是線程安全的,但我可以做到這一點。問題是:如何組織循環? 如果要寫'while(true)',它會產生很多額外的請求。 – Zharro