Есть два решения. Быстрым и грязным было бы добавить счетчик, чтобы указать количество оставшихся заданий, которое будет увеличиваться, как и до вызова 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, где бы вы ни вызывали этот метод, либо иметь другой обратный вызов для обработки завершения
Вы могли записать свое собственное средство выделения для контейнера, который выделяет от фиксированного размера статический буфер. В зависимости от шаблонов использования контейнера средство выделения могло быть столь же простым как постепенное увеличение указателя (например, когда Вы только вставляете материал в контейнер однажды при запуске приложения и непрерывно не добавляете/удаляете элементы.)
Мы используем повышение для встроенных систем. С повышением можно привередливо выбрать то, что Вы используете. Мы используем smart_ptr
и boost::bind
во всех наших проектах. Мы пишем программное обеспечение для дешевых сотовых телефонов. И если бы Windows CE может работать на Ваших аппаратных средствах, я ожидал бы, что части повышения были бы применимы. Существуют части повышения, которые не имеют никакого выделения, и Вы могли бы найти их полезными.
Я привередничал бы на основе Ваших требований.
Как что-либо, что Вы используете, необходимо знать затраты.
Замена Ваших контейнеров с контейнерами Повышения НЕ является хорошей идеей. Работа для создания соответствующих пользовательских средств выделения не состояла бы в том, что плохо, но Вы будете нарушать дух Ваш, 'выделяют при запуске' правило. Идея позади этого правила (по моему опыту), состоит в том, чтобы обычно удостоверяться, что Вы не должны иметь дело с из ситуаций с типом памяти во времени выполнения. Идея состоит в том, чтобы удостовериться, что у Вас есть вся память, в которой Вы могли возможно нуждаться прямо В ЗАПУСКЕ, так, чтобы не было никакой возможности никакой части системы, подходящей за исключением памяти позже.
При использовании контейнеров Повышения с пользовательским средством выделения необходимо было бы внезапно иметь дело с возможностью, что пул, от которого выделяет контейнер, мог пойти пустой, таким образом устранение цели 'выделяет при запуске' правило.
В ситуации устройства ограниченной памяти я избежал бы любого вида контейнера, более сложного, чем статически выделенный массив.
Повышение является рядом библиотек. Некоторые из них фокусируются на шаблонном метапрограммировании. Они даже не используют памяти во времени выполнения. Но Ваш вопрос, кажется, о замене Ваших контейнеров. Я сомневался бы, что это возможно кроме использования пользовательских средств выделения. Но даже затем, наиболее вероятно, что Вы использовали бы плоскость контейнеры STL и не повышение. Повышение только обеспечивает контейнеры TR1 для тех компиляторов, которые еще не включают TR1.
Не используйте Повышение.
Это - крупная библиотека, и Ваши требования выделения основной памяти очень отличаются от тех из разработчиков библиотек.
Даже если можно заставить текущую версию Повышения работать согласно требованиям с пользовательскими средствами выделения, оно может порвать с новой версией Повышения.
Не стесняйтесь смотреть на исходный код Повышения, хотя для некоторых полезных идей, но используют Вашу собственную реализацию для того, в чем Вы нуждаетесь.