Есть два решения.Быстрым и грязным было бы добавить счетчик, чтобы указать количество оставшихся заданий, которое будет увеличиваться, как и прежде, вызывать GetResponse
и уменьшаться в пределах обратного вызова, а если оно достигает 0, вызовите следующий шаг в вашем процессе.Это было бы рискованно из-за состояния гонки и непредсказуемого поведения потока, например, если вы вызываете один запрос и до того, как второй запрос начнется, а затем он попытается продолжить.
Лучшим решением было бы отслеживатьЗадачи, созданные с помощью OpenReadTaskAsync
вместо OpenReadAsync
, а затем с помощью Task.WhenAll({ALL YOUR TASKS})
.
Это немного изменит вашу программу:
List<Result> result = new List<Result>();
List<Task<Stream>> jobs = new List<Task<Stream>>();
...
GetResponse
должен будет вернуть значение задачи, которое является простым.
private Task<Stream> GetResponse(Uri uri, Action<MyResponse> callback)
{
... //Almost all of your code stays the same,
//though you should close the stream you receive in the OnReadCompleted callback.
return m_webClient.OpenReadTaskAsync(uri.ToString());
}
Последний в методе FillResults
, вы должны добавить эти задачи в список и ждать.
public async Task FillResults()
{
foreach( var urlx in Urls)
{
jobs.Add(
GetResponse(urlx, (response) =>
{
if (response != null && response.StatusCode==200)
{
Result result=new Result;
result.Value=response.SomeValue;
result.url=urlx;------>It is important that SomeValue corresponds to urlx and not other say,urly
results.Add(result);
}
})
);
}
await Task.WhenAll(jobs);
//Or Task.WhenAll(jobs).ContinueWith({AN ACTION CALLBACK})
//if you want to keep the return as a void;
}
Теперь вы можете либо ожидать функцию FillResults, где бы вы ни вызывали этот метод, либо иметь другой обратный вызов для обработки завершения