Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.11.2014, 14:35   #1
L6go1as
Форумчанин
 
Регистрация: 20.10.2011
Сообщений: 433
По умолчанию Универсальный метод или как развести ?

Уважаемые, подскажите как правильно развести по событиям\методам.

Создаю экзепляр вэбклиента и эвентом вывожу данные.
Однако, если создание вэбклиента запустить в цикле, то в эвенте будет выводиться информация каждого экземпляра, что делает такую инфу бесполезной.

Собственно вопрос, как развести вновь созданные экземпляры и эвенты ?
Смотрю в сторону универсальных методов, однако, правильно задать не получается.

Может кто сталкивался, как распаралелить ?
L6go1as вне форума Ответить с цитированием
Старый 02.11.2014, 15:08   #2
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Не понял о чем вопрос и какую проблему решаем, но как минимум в методе-обработчике события в параметрах есть объект его создавший.

"Универсальные" это generic что ли? И чем они помогут, что вы с ними делать хотите?
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 02.11.2014, 15:28   #3
L6go1as
Форумчанин
 
Регистрация: 20.10.2011
Сообщений: 433
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Не понял о чем вопрос и какую проблему решаем, но как минимум в методе-обработчике события в параметрах есть объект его создавший.

"Универсальные" это generic что ли? И чем они помогут, что вы с ними делать хотите?
Вот это в цикле
Код:
WebClient wb = new WebClient();
                    try
                    {
                        wb.DownloadFileAsync(new Uri(url[i]), file[i]);
                        wb.DownloadProgressChanged += wb_DownloadProgressChanged;
                        wb.DownloadFileCompleted += wb_DownloadFileCompleted;
                        
                        wb.Dispose();
                    }
                    catch { }
Проблема в том, что если больше 1 экземпляра создано, то в wb_DownloadProgressChanged выводятся результаты сразу двух экземпляров, что не читабельно.

Как сделать так, что бы wb_DownloadProgressChanged выводил инфу для нескольких экземпляров ?

А универсальные методы - эт вот что имею введу:

http://msdn.microsoft.com/ru-ru/library/twcad0zb.aspx

т.е. wb_DownloadProgressChanged<i> - как я понимаю.
L6go1as вне форума Ответить с цитированием
Старый 02.11.2014, 15:44   #4
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

"нечитабельность" зависит только от того, что и для чего вам надо прочитать.

Чтобы идентифицировать webclient в методе-обработчике есть параметр, в котором передается ссылка на объект, который сгенерировал событие.

Цитата:
А универсальные методы - эт вот что имею введу
Ну я и говорю generic. Первый раз услышал чтоб их называли универсальными, по-моему даже в русскоязычных текстах их обычно называют generic, или хотя бы шаблонами (но это скорее для template в С++).

Цитата:
т.е. wb_DownloadProgressChanged<i> - как я понимаю.
Что-то вы не так поняли. Пример применения generic-ов: класс-коллекция (List<T>, Queue<T> и т.д.), в которой можно хранить любые объекты. Чтобы не создавать отдельный класс для int, string, MyMegaClass и т.д., а просто указать тип при создании объекта, который будет там храниться — new List<int>();
Когда не было generic (< .NET 2.0) были коллекции просто для object (ArrayList), что не очень удобно, постоянно приводить к нужному типу при доступе к элементам коллекции и т.д.

И тем более нельзя сделать не generic метод generic-ом. Он либо такой изначально, либо нет.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.

Последний раз редактировалось Alex11223; 02.11.2014 в 16:08.
Alex11223 вне форума Ответить с цитированием
Старый 02.11.2014, 15:51   #5
L6go1as
Форумчанин
 
Регистрация: 20.10.2011
Сообщений: 433
По умолчанию

Ну скажем прогресс бар обновляется сразу для всех созданных элементов, т.е. постоянно "дергается" то вперед, то назад.
Для отображения тех же % - то больше, то меньше из-за разного веса файлов.

Приведите пожалуйста пример, как должно быть реализовано, а то уже голова кипит.
L6go1as вне форума Ответить с цитированием
Старый 02.11.2014, 16:04   #6
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Дергался это как? Они ж параллельно загружаются, а не последовательно. Обычно либо складывают размер всех файлов для макс. значения прогрессбара, либо отдельный для каждого.

Кстати, а зачем там Dispose? Вы ж только запустили загрузку (в другом потоке), но не факт, что она уже завершилась.

и try catch {} без адекватной обработки исключений в catch — обычная плохая идея. (зависит от задачи, но хотя бы в какой-нибудь лог записать, а то так никто и не узнает об ошибке и будет удивляться почему всё молча не работает).
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 02.11.2014, 16:12   #7
L6go1as
Форумчанин
 
Регистрация: 20.10.2011
Сообщений: 433
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Дергался это как? Они ж параллельно загружаются, а не последовательно. Обычно либо складывают размер всех файлов для макс. значения прогрессбара, либо отдельный для каждого.

Кстати, а зачем там Dispose? Вы ж только запустили загрузку (в другом потоке), но не факт, что она уже завершилась.

и try catch {} без адекватной обработки исключений в catch — обычная плохая идея. (зависит от задачи, но хотя бы в какой-нибудь лог записать, а то так никто и не узнает об ошибке и будет удивляться почему всё молча не работает).
Вот для "либо отдельный для каждого" - это интересует, я как раз от общего уйти хочу.

По Dispose, то исходя из async то по идее экземпляр будет убиваться строго после загрузки. (как я думаю, хотя в тестовом режиме 100 файлов скачалось и убились клиенты без ошибок)

Что до try catch, то файлы качаются из нестабильного сервера, который часто не доступен, таким образом исключения не прерывают работу программы, т.е. скажем для 1 - 10 файлов сервер доступен, до с 10 по 80 сервер не доступен, а дальше опять работает.
При такой конструкции закачка работает максимально эффективно (качает все что доступно на данный момент).

тут больше интересует как сделать вывод информации для каждого экземпляра отдельно. (что вы и предложили выше).
L6go1as вне форума Ответить с цитированием
Старый 02.11.2014, 16:35   #8
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
По Dispose, то исходя из async то по идее экземпляр будет убиваться строго после загрузки.
Не должен. Что-то похожее возможно только при использовании async/await из C#5.
Смысл метода в том, что при вызове DownloadFileAsync он запускает загрузку в другом потоке, а текущий поток не блокируется (в отличии от DownloadFile) и идет дальше (вызывая Dispose).

Цитата:
Что до try catch, то файлы качаются из нестабильного сервера, который часто не доступен
Ну вы все равно не поймаете тут ошибку загрузки, разве что некорректный url (null и т.п.). Она в DownloadFileCompleted будет (в свойствах его eventargs).

Цитата:
тут больше интересует как сделать вывод информации для каждого экземпляра отдельно.
Ну например можно сделать список/массив ProgressBar'ов и
  • либо Dictionary (Dictionary<WebClient, ProgressBar>), куда в цикле создания/запуска заносить i-й progressbar и wb
  • либо тоже просто список WebClient.
И потом в обработчике события
Код:
void wb_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
брать sender (его привести к WebClient: WebClient wb = (WebClient) sender; ) и либо из Dictionary по нему доставать ProgressBar, либо в массиве вебклиентов искать индекс и брать по нему из массива прогресбаров.

Или такой более краткий вариант с лямбдой:
Код:
        private List<ProgressBar> progressBars = new List<ProgressBar>();
        private List<string> urls = new List<string>();
        private List<string> files = new List<string>(); 

        private void button1_Click(object sender, EventArgs e)
        {
            // просто создание списка данных и прогрессбаров для примера
            if (urls.Count == 0)
            {
                for (int i = 0; i < 10; i++)
                {
                    urls.Add("http://programmersforum.ru");
                    files.Add(i + ".html");
                    progressBars.Add(new ProgressBar()
                    {
                        Parent = this,
                        Left = 1,
                        Top = 100 + 30*i,
                        Height = 25,
                        Width = 250,
                        Maximum = 100
                    });
                }
            }

            for (int i = 0; i < urls.Count; i++)
            {
                var wb = new WebClient();

                var pb = progressBars[i];
                wb.DownloadProgressChanged += (o, args) =>
                {
                    pb.Value = args.ProgressPercentage;
                };

                wb.DownloadFileAsync(new Uri(urls[i]), files[i]);
            }
        }
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.

Последний раз редактировалось Alex11223; 02.11.2014 в 17:15.
Alex11223 вне форума Ответить с цитированием
Старый 02.11.2014, 18:08   #9
L6go1as
Форумчанин
 
Регистрация: 20.10.2011
Сообщений: 433
По умолчанию

Alex11223, благодарю! все работает как часы!

Код:
wb.DownloadProgressChanged += (o, args) =>
                {
                    pb.Value = args.ProgressPercentage;
                };
Не могли бы объяснить что тут происходит ? Насколько, создается псевдо переменные о, args и под лямдой передается каждому прогресс бару нужное событие ?
Если не затруднит расскажите по подробнее
А так же интересен ваш вариант с WebClient: WebClient wb = (WebClient) sender;

Я не увидел вашего сообщения и начал через делегат писать ... с переменным успехом правда - не думаю что делегат в данной ситуации вообще бы сработал (можно ваш комментарий по данному поводу)

Спасибо в любом случае!
L6go1as вне форума Ответить с цитированием
Старый 02.11.2014, 18:20   #10
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

o и args это параметры метода. Тоже, что и в

Код:
void wb_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
Тут просто создается 10 методов вместо 1 и в каждом нужный ProgressBar используется.

Цитата:
А так же интересен ваш вариант с WebClient: WebClient wb = (WebClient) sender;
Да это просто, чтобы привести из object к WebClient. Ну или изначально в списке/словаре вебклиентов object'ы хранить.

Код:
        private void wb_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            var wb = (WebClient) sender;

            int ind = webClients.IndexOf(wb);

            progressBars[ind].Value = e.ProgressPercentage;
        }
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Процедуры и функции как метод класса, или... Pcrepair Общие вопросы Delphi 4 03.09.2013 21:32
Интернет магазины или как не дать себя развести whatever Свободное общение 13 17.04.2013 00:15
MS SQL Server: универсальный Logger сделанный как триггер Glen SQL, базы данных 8 11.03.2013 13:59
Как объявлять (или описывать) метод locate? Andr_zdes Помощь студентам 6 21.05.2009 14:22
Как создать универсальный шаблон документа? CoolMan Microsoft Office Word 1 18.12.2007 09:10