Вот такой пример запускаем 100 Task. для загрузки html. c одного сайта,
в синхронной версии программа работает в асинхронной не завершается?
Всегда остается 10-15 ждущих?
Почему?
Запускаем
private void button2_Click(object sender, EventArgs e)
{
for (int i = 0; i < 100; i++)
{
Task.Factory.StartNew(
() =>
{
DoLongWork();
}
);
}
}
count_end — не доходит до 100 в асинхронной версии?
Какие могут быть причины?
1. Что-то не так в коде с lock!
2. У DownloadStringCompleted — нет таймаута по умолчанию?
3?
Спасибо за любой совет.
Re: WebClient не всегда работает?
От:
Аноним
Дата:
23.03.13 09:36
Оценка:
Здравствуйте, yniker, Вы писали:
Может быть экземпляр WebClient собирается сборщиком мусора? попробуй их куда-нибудь сохранять.
Ну с локом норм, но лучше Interlocked.Increment заюзать.
1. Какую конкретно задачу ты пытаешься решить?
2. Почему WebClient объект один на все потоки?
3. Почему запуск асинхронного метода DownloadStringAsync делается также асинхронно?
Я могу прослыть банальным и любителем producer/consumer паттерна (в соседней ветке уже рекомендовал), но он тут тоже подходит...
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, yniker, Вы писали:
А>Может быть экземпляр WebClient собирается сборщиком мусора? попробуй их куда-нибудь сохранять.
Кстати, это вполне возможно. Действительно, мы создаем WebClient, запускаем все асинхронно, и теряем на него ссылки.
А в соседней ветке я ошибся — думал там один на всех.
Здравствуйте, vvlad.net, Вы писали:
VN>Здравствуйте, yniker, Вы писали:
VN>2. Почему WebClient объект один на все потоки?
Сорри, ошибся — см. http://rsdn.ru/forum/dotnet/5110157.1
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, yniker, Вы писали:
А>Может быть экземпляр WebClient собирается сборщиком мусора? попробуй их куда-нибудь сохранять.
Переписал метод с Nlog. что-бы оптимизатор .NET не удалял обьект.
1. Правильно ли я понимаю, что теперь никакой оптимизатор или сборщик памяти не удалит webclient я ведь от него жду результат.
2. Да кстати на другом ПК, первый вариант отлично работает. Но это меня совсем не устраивает у конечного пользователя может быть зоопарк антивирусов и firewall.
А все должно работать стабильно.
Здравствуйте, vvlad.net, Вы писали:
VN>Здравствуйте, yniker, Вы писали:
Y>> много чего...
VN>Ну с локом норм, но лучше Interlocked.Increment заюзать.
VN>1. Какую конкретно задачу ты пытаешься решить?
Задача простая.
Есть миллионы Задач, задача состоит в следующем.
Скачать одну страницу, проанализировать результат, скачать еще одну страницу,
проанализировать результат, записать результат в базу.
С максимально возможной производительностью.
Варианты решения, синхронная версия.
1.
Решение в лоб, создаем 1000-2000 потоков, и спокойно синхронно, все это выполняем.
Минусы понятны, память, переключение между потоками.
2. ThreadPool — не даст нам одновременно 1000-2000 закачек сделать, или же создаст опять таки 1000-2000 реальных потоков. Со временем.
3. Task — тоже самое что и ThreadPool.
Варианты решения, асинхронная версия.
4. await я так понимаю будет тоже самое., хотя могу ошибаться.
Варианты решения, асинхронная версия.
VN>2. Почему WebClient объект один на все потоки? VN>3. Почему запуск асинхронного метода DownloadStringAsync делается также асинхронно?
Вот тут начинаются проблемы.
Вот тут начинаются проблемы.
везде написано, что асинхронно крутто и.т.д. но на самом деле
DownloadStringAsync это же только НАПОЛОВИНУ асинхронная штука, не пойму зачем microsoft такую бяку сделали.
Ведь получение DNS и Proxy — там синхронно, да не много по времени 1-15 секун, но СИНХРОННО и в реальном приложении это уже большая проблема, вот которую я как раз и немогу пока как то правильно решить.
именно поэтому я в начале запускаю Task 100 штук, а там вызываю асинхронно webclient.
Хотя этот метод тоже не идеален, на время синхронизации мы получаем тормоза, да и 1000 задач не одновременно запустится, как бы хотелось, а постепенно.
VN>Я могу прослыть банальным и любителем producer/consumer паттерна (в соседней ветке уже рекомендовал), но он тут тоже подходит...
Тоже рассматриваю вариант, но пока не могу его применить логически для своей задачи. Не могу толком понять применимость.
Здравствуйте, _Raz_, Вы писали:
_R_>Здравствуйте, yniker, Вы писали:
Y>>Какие могут быть причины? Y>>3?
_R_>Может посмотреть в сторону ServicePointManager.DefaultConnectionLimit?
у меня стоит ServicePointManager.DefaultConnectionLimit = 1000;
Да и причем здесь это, в моем примере, проблема, не в том насколько БЫСТРО это отрабатывает, а в том что на моем ПК асинхронный метод вообще не завершается.
Re[3]: WebClient не всегда работает?
От:
Аноним
Дата:
23.03.13 12:02
Оценка:
Здравствуйте, yniker, Вы писали:
Y>1. Правильно ли я понимаю, что теперь никакой оптимизатор или сборщик памяти не удалит webclient я ведь от него жду результат.
Нет, попробуй экземпляр WebClient сохранить в какой-нибудь List перед DownloadStringAsync
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, yniker, Вы писали:
Y>>1. Правильно ли я понимаю, что теперь никакой оптимизатор или сборщик памяти не удалит webclient я ведь от него жду результат. А>Нет, попробуй экземпляр WebClient сохранить в какой-нибудь List перед DownloadStringAsync
побывал и через list, все аналогично.
Хотя подробней узнать было бы интересно почему, в предыдущей реализации может быть потеря ссылки.
Не исключено тогда, что и текущая с list не правильная реализация.
Как правильно тогда?
PS, большое спасибо всем за ответы.
List<WebClient> List=new List<WebClient>();
private void Form1_Load(object sender, EventArgs e)
{
ServicePointManager.DefaultConnectionLimit = 1000;
for (int i = 0; i < 100; i++)
{
List.Add(new WebClient());
}
}
void DoLongWork()
{
int index = 0;
lock (thisLock)
{
count_start++;
index = count_start - 1;
}
//Вариант №1
Variant1(List[index]);
//Вариант №2
//Variant2(List[index]);
}
Re[5]: WebClient не всегда работает?
От:
Аноним
Дата:
23.03.13 12:25
Оценка:
Здравствуйте, yniker, Вы писали:
Y>побывал и через list, все аналогично.
Тогда сдаюсь
Y>Хотя подробней узнать было бы интересно почему, в предыдущей реализации может быть потеря ссылки.
С одной стороны раз есть подписанный ивент то потери ссылки быть не должно.
С другой — когда ты так подписываешься и наверняка подразумеваешь, что исходный объект будет собран когда не будет нужен.
Если разработчики фреймворка ориентировались на такой сценарий, то возможно события реализованы с помощью слабых ссылок, и тогда сборщик мусора может прибить объект если на него не осталось явных ссылок. Если нет, и в подписке честные ссылки, то будет утечка памяти без отписки.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, yniker, Вы писали:
Y>>побывал и через list, все аналогично. А>Тогда сдаюсь
Y>>Хотя подробней узнать было бы интересно почему, в предыдущей реализации может быть потеря ссылки. А>С одной стороны раз есть подписанный ивент то потери ссылки быть не должно. А>С другой — когда ты так подписываешься и наверняка подразумеваешь, что исходный объект будет собран когда не будет нужен. А>Если разработчики фреймворка ориентировались на такой сценарий, то возможно события реализованы с помощью слабых ссылок, и тогда сборщик мусора может прибить объект если на него не осталось явных ссылок. Если нет, и в подписке честные ссылки, то будет утечка памяти без отписки.
Событие, DownloadStringCompleted
Это единственный вариант получить ответ от DownloadStringAsync, не думаю что тут могут быть вообще слабые ссылки.
Задана работа и нужен результат, а его нет.
Может сам по себе WebClient жутко стабильная штука?
Re: WebClient не всегда работает?
От:
Аноним
Дата:
23.03.13 12:40
Оценка:
Здравствуйте, yniker, Вы писали:
Изменил Ваш код, добавив вывод сообщения об окончании загрузки. Прогон показал, что всё работает нормально. Отсюда вопрос: почему в асинхронной версии
Вы не обрабатываете исключения? Ведь они просто завершают поток и проглатываются, т.к. к результату Task не обращаетесь.
Здравствуйте, yniker, Вы писали:
Y>Тоже рассматриваю вариант, но пока не могу его применить логически для своей задачи. Не могу толком понять применимость.
Уже понятно.
разбей твою задачу на подзадачи:
— вместо скачать-проанализировать-скачать-сохранить
— станет:
1. producer pushes download task to queue
2. consumer takes the task, downloads
3. consumer becomes producer — pushes downloaded result to queue
4. consumer (another one maybe) — takes the downloaded result, analyses it
5. consumer becomes producer — pushes download task (analyse result) to queue
6. consumer takes the task to download, pushes thre sult to queue
7. consumer takes the result, saves it to db
that's all.
Количество консумеров — количество потоков, не будет простоя.
В самих консумерах юзай пока синхронный вариант, тебе опыта не хватит заюзать асинхронный,
да и не особо это и критично для твоей задачи.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, yniker, Вы писали: А>Изменил Ваш код, добавив вывод сообщения об окончании загрузки. Прогон показал, что всё работает нормально. Отсюда вопрос: почему в асинхронной версии А>Вы не обрабатываете исключения? Ведь они просто завершают поток и проглатываются, т.к. к результату Task не обращаетесь.
Можно увидеть ваш код.
Я повторюсь на другом ПК у товарища тоже работает.
Здравствуйте, Аноним, Вы писали:
А>Ведь они просто завершают поток и проглатываются, т.к. к результату Task не обращаетесь.
Извиняюсь, похоже глупость сказал.
Re[7]: WebClient не всегда работает?
От:
Аноним
Дата:
23.03.13 12:58
Оценка:
Кстати, если проблема воспроизводится под отладчиком, то можно приостановить выполнение и посмотреть на активные потоки и их стэк трейсы.
По крайней мере понятно будет, завис ли клиент или потерялся результат.
Здравствуйте, vvlad.net, Вы писали:
VN>Здравствуйте, yniker, Вы писали:
Y>>Тоже рассматриваю вариант, но пока не могу его применить логически для своей задачи. Не могу толком понять применимость.
VN>Уже понятно.
VN>разбей твою задачу на подзадачи: VN>- вместо скачать-проанализировать-скачать-сохранить VN>- станет:
VN>1. producer pushes download task to queue VN>2. consumer takes the task, downloads VN>3. consumer becomes producer — pushes downloaded result to queue VN>4. consumer (another one maybe) — takes the downloaded result, analyses it VN>5. consumer becomes producer — pushes download task (analyse result) to queue VN>6. consumer takes the task to download, pushes thre sult to queue VN>7. consumer takes the result, saves it to db
VN>that's all.
VN>Количество консумеров — количество потоков, не будет простоя. VN>В самих консумерах юзай пока синхронный вариант, тебе опыта не хватит заюзать асинхронный, VN>да и не особо это и критично для твоей задачи.
Спасибо буду анализировать ваш вариант, главное что-бы он еще логику работы не усложнил. Так что больше некуда.
На самом деле не просто закачка, а множественный анализа данных и много разных если.. задача больше похожа на черный ящик. с кучей подзадач.
Спасибо еще вопрос, если где стандартные красивые может, обертки producer-consumer, что-то вроде кода,
Здравствуйте, yniker, Вы писали:
Y>Спасибо буду анализировать ваш вариант, главное что-бы он еще логику работы не усложнил. Так что больше некуда. Y>На самом деле не просто закачка, а множественный анализа данных и много разных если.. задача больше похожа на черный ящик. с кучей подзадач.
Каждое длительное действие — задача (закачка, запись в базу данных...)
Во время анализа — если нужно закачать, а потом проверить результат —
займись пересмотром логики анализа, или просто — новые задачи: закачать, продолжить анализ.
Y>Спасибо еще вопрос, если где стандартные красивые может, обертки producer-consumer, что-то вроде кода,