Я пытаюсь написать приложение winforms, которое извлекает список идентификаторов из веб-службы SOAP, затем просматривает этот список, вызывая другой веб-сервис, чтобы получить индивидуальные сведения. Чтобы ускорить процесс, я выполняю эти запросы параллельно, партиями по 15.
Когда все вызовы веб-службы возвращаются в порядке, мое приложение работает отлично. Однако в моем тестировании, если время ожидания двух или более запросов (я отслеживаю запросы с помощью Fiddler и вижу, что получаю 408), то кажется, что процесс зависает, и я никогда не получаю сообщение о завершении, которое должны отображать мои программы.
Что бы я хотел сделать, если это возможно, это повторить эти запросы или просто попросить пользователя снова нажать кнопку, поскольку произошла ошибка.
При добавлении ссылки на службу я убедился использовалась опция генерирования операций на основе задач.
Вот код, который я получил до сих пор (некоторые детали переименованы, чтобы не выдавать компанию, с которой я взаимодействую):
private async void btnDownload_Click(object sender, EventArgs e)
{
try
{
Stopwatch watch = new Stopwatch();
watch.Start();
IProgress<string> progress = new Progress<string>(s =>
{
lbinfo.Items.Insert(0, s);
});
await GetData(progress);
watch.Stop();
progress.Report("Took " + (watch.ElapsedMilliseconds / 1000f) + " seconds. All done.");
}
catch(Exception ex)
{
MessageBox.Show("Main Click: "+ex.ToString());
}
}
private async Task GetData(IProgress<string> progress)
{
try
{
DownloadSoapClient client = new DownloadSoapClient();
client.Open();
progress.Report("Getting master list.");
List<int> uniqueIds = await GetMasterList(client); //this always seems to work
progress.Report("Downloaded master list. Found "+uniqueIds.Count +" unique ids.");
var detailedData = await GetIdDataRaw(uniqueIds, client,progress);
client.Close();
}
catch (Exception ex)
{
progress.Report("GetData: "+ex);
}
}
private async Task<List<DownloadResponse>> GetIdDataRaw(List<int> ids, DownloadSoapClient client, IProgress<string> progress)
{
using (var throttler = new SemaphoreSlim(15))
{
var allTasks = ids.Select(async x =>
{
await throttler.WaitAsync();
try
{
progress.Report(x.ToString());
return await client.DownloadAsync(username, password, x);
}
catch (Exception ex)
{
progress.Report("Error getting id:" + x + " " + ex.Message);
return null;
}
finally
{
throttler.Release();
}
});
return (await Task.WhenAll(allTasks)).ToList();
}
}
Как правило, главный список составляет около 1000 записей, и, когда он выходит только 1 раз, как и ожидалось, я получаю сообщение о том, что произошла ошибка при получении идентификатора xxxx, а затем «Прошло xx секунд. Все сделано».
До сих пор я пробовал несколько других вещей, таких как создание клиента для каждого запроса и рефакторинг для использования Task.WhenAny через некоторое время l oop, но они демонстрируют то же поведение, когда 2 или больше запросов не удается.