Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
87 / 55 / 15
Регистрация: 01.10.2010
Сообщений: 492

Передача обработчиков событий в конструктор

26.02.2016, 09:29. Показов 1780. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Можно ли передавать обработчики событий в конструктор как параметры, если да, то как?

Более общая задача.

Есть операция, которая длится большой промежуток времени, но её можно разбить на мелкие стадии. Пользователю надо сообщать о прогрессе.

Идея такая: на стороне бизнес-логики в класс добавил функционал, чтобы метод (хотя более уместен термин "некая операция"), мог сообщать клиенту о своём прогрессе.

Реализовал так.

Бизнес-логика.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class WasInfoBuilder
{
 
public BackgroundWorker BuildApplicationAllInfoBackgroundWorker { get; set; }
 
public WasInfoBuilder()
        {
            BuildApplicationAllInfoBackgroundWorker = new BackgroundWorker();
            BuildApplicationAllInfoBackgroundWorker.WorkerReportsProgress = true;
            BuildApplicationAllInfoBackgroundWorker.DoWork += BuildApplicationAllInfoBackgroundWorker_DoWork;
        }
 
private void BuildApplicationAllInfoBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
...
BuildApplicationAllInfoBackgroundWorker.ReportProgress(10, "- Этап 1");
...
BuildApplicationAllInfoBackgroundWorker.ReportProgress(20, "- Этап 2");
...
}
 
public void BuildApplicationAllInfo()
        {
            BuildApplicationAllInfoBackgroundWorker.RunWorkerAsync();
        }
 
}
Клиент.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
private void UpdateWasInfo()
        {
            WasInfoBuilder wasInfoBuilder = new WasInfoBuilder();
            wasInfoBuilder.BuildApplicationAllInfoBackgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged;
            wasInfoBuilder.BuildApplicationAllInfoBackgroundWorker.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted;
            wasInfoBuilder.BuildApplicationAllInfo();
        }
 
private void BackgroundWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            ProgressUserControl.ProgressBar.Value = e.ProgressPercentage;
            ProgressUserControl.LogTextBox.AppendText(e.UserState + "\r\n");
        }
Подписываться каждый раз на нужные события не очень красиво, подумал, что может можно как-то через параметры передать обработчики.

P.S. Если кто-то предложит более простую идею/реализацию буду благодарен
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.02.2016, 09:29
Ответы с готовыми решениями:

Несколько обработчиков событий
Ситуация следующая, имеется несколько обработчиков различных событий, когда события зажгутся не известно. Есть новый метод, логику...

Динамическая создание обработчиков событий
Суть в следующем. На формочку динамически накидываются ЧекБоксы. Они представляют собой категории и подкатегории. Необходимо чтобы при...

Отлов событий webBrowser, отваливаются часть стандартных обработчиков.
Проблема в том что когда пытаюсь добавить обработчик, почти любого, события к webBrowser, отваливается часть стандартных обработчиков, мб...

15
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
26.02.2016, 12:15
Цитата Сообщение от MDmitry_ Посмотреть сообщение
более простую идею/реализацию буду благодарен
Не совсем понял вопроса и ваш код. Я сам делаю проще, когда нужен всего один дополнительный поток для выполнения долгой операции-создаю класс, наследую его от BackgroundWorker, переопределяю метод OnDoWork() и в нем пишу свой функционал. Если надо несколько методов, пожалуйста, пишем их в этом классе и потом используем внутри этого переопределенного метода.
1
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
26.02.2016, 18:55
Цитата Сообщение от MDmitry_ Посмотреть сообщение
Можно ли передавать обработчики событий в конструктор как параметры, если да, то как?
Конечно передавать можно:
C#
1
2
3
4
5
6
7
        public WasInfoBuilder(ProgressChangedEventHandler progressHandler)
        {
            BuildApplicationAllInfoBackgroundWorker = new BackgroundWorker();
            BuildApplicationAllInfoBackgroundWorker.WorkerReportsProgress = true;
            BuildApplicationAllInfoBackgroundWorker.ProgressChanged += progressHandler;
            //...
        }
Но в целом, я бы не стал запихивать BackgroundWorker в объекты бизнес-логики. Распараллеливание по потокам - должно инициироваться в слое GUI, но не объектами BL. Зачем объектам BL какие-то BackgroundWorker-ы? Для вашей логики они нужны? Нет. Значит они там лишние. А если слой GUI не устраивает долгая работа BL, то это он должен создавать дополнительные потоки и управлять ими. Или другой пример - вы запускаете свой BL не в десктопном приложении, а на сервере. Зачем в таком случае BL отдельный поток? Сервер все равно будет ждать завершения операции целиком. Т.о. для серверного варианта, ни доп поток, ни прогресс - не нужны.
Единственное что должен реализовать ваш BL объект - это событие типа ProgressChanged, что бы внешний слой мог подписаться на него и узнавать прогресс выполнения. Но BackgroundWorker в BL создаваться не должен. ИМХО.
1
87 / 55 / 15
Регистрация: 01.10.2010
Сообщений: 492
27.02.2016, 14:14  [ТС]
Пользователь хочет видеть прогресс и чихать ему на то, что не может быть реализовано это, потому что в БЛ что-то быть не должно.

Цитата Сообщение от Storm23 Посмотреть сообщение
Единственное что должен реализовать ваш BL объект - это событие типа ProgressChanged, что бы внешний слой мог подписаться на него и узнавать прогресс выполнения. Но BackgroundWorker в BL создаваться не должен. ИМХО.
Не совсем понял. Зачем реализовывать что-то своё, если можно взять готовый BackgroundWorker?

Цитата Сообщение от Storm23 Посмотреть сообщение
Распараллеливание по потокам - должно инициироваться в слое GUI, но не объектами BL.
В целом согласен, но нет идей как это сделать так. В GUI можно всё это дело выделить в отдельный поток, но встаёт тогда вопрос: как узнать прогресс? Можно в GUI дёргать отдельные мелкие стадии большой операции, но тогда встаёт вопрос: зачем тогда нужна БЛ?

Добавлено через 2 минуты
Цитата Сообщение от insite2012 Посмотреть сообщение
Я сам делаю проще, когда нужен всего один дополнительный поток для выполнения долгой операции-создаю класс, наследую его от BackgroundWorker, переопределяю метод OnDoWork() и в нем пишу свой функционал.
Мда... Про наследование я почему-то всегда забываю, а оно иногда бывает довольно удобным.

А если такая ситуация. Есть несколько долгих операций и они используют поля одного класса и по логике с ним связаны. Тогда что бы сделали?
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
27.02.2016, 17:10
Цитата Сообщение от MDmitry_ Посмотреть сообщение
Есть несколько долгих операций и они используют поля одного класса и по логике с ним связаны. Тогда что бы сделали?
Тут все зависит от связи этих долгих операций.
Если они являются одним логическим блоком и должны выполняться одна за другой, тогда бы просто определил их в разных методах и вызывал их последовательно в методе OnDoWork().
0
87 / 55 / 15
Регистрация: 01.10.2010
Сообщений: 492
29.02.2016, 12:40  [ТС]
Нет, они не являются одним логическим блоком
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
29.02.2016, 13:41
Цитата Сообщение от insite2012 Посмотреть сообщение
Я сам делаю проще, когда нужен всего один дополнительный поток для выполнения долгой операции-создаю класс, наследую его от BackgroundWorker, переопределяю метод OnDoWork() и в нем пишу свой функционал.
а зачем такие сложности? Лично мне достаточно задать обработчик события DoWork, в особых случаях определить передаваемый в поток аргумент.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
29.02.2016, 13:49
Цитата Сообщение от aquaMakc Посмотреть сообщение
а зачем такие сложности?
Чтобы инкапсулировать всю логику работы в одном объекте, естественно.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
29.02.2016, 13:51
insite2012, ну так кроме наследования есть еще и композиция. Я тоже не вижу смысла переопределять OnDoWork, когда есть удобное событие. А переопределять дефолтное поведение этого класса мне кажется неправильным. Можно потом отхватить. Ну и логично, когда свой класс предоставляет 2-3 нужных метода, а у BackgroundWorker миллиард всяких методов и свойств, которые вызывающему коду не нужны, а может и вообще ломают внутреннюю логику обработки.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
29.02.2016, 14:01
Цитата Сообщение от Psilon Посмотреть сообщение
переопределять дефолтное поведение этого класса мне кажется неправильным. Можно потом отхватить.
Албахари с вами не согласен.
Ну а по сути, кому как удобно (выше уже об этом говорилось). Когда нужно быстро и без особых хлопот - мне так подходит.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
29.02.2016, 14:11
insite2012, Argumentum ad verecundiam - не катит. Наследование - достаточно старая концепция, и её придерживаются просто по привычке. Ну и иногда она лучше. Но когда тащится АПИ чужого класса, чтобы запрограммировать поведение своего - это явно неправильно
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
29.02.2016, 14:18
Цитата Сообщение от Psilon Посмотреть сообщение
Но когда тащится АПИ чужого класса, чтобы запрограммировать поведение своего - это явно неправильно
Почему? Выходит, если мне нужен свой List<T>, который по многим характеристикам будет отвечать стандартной реализации, но с небольшим изменением, то наследование от стандартного-зло? Писать свой с нуля? Зачем? Тогда наследование вообще не нужно, давайте везде использовать композицию.
И это касается не только приведенного примера, а и всего остального. Возьмем любой контрол, если мне нужно изменить его поведение (не все, а часть) - мне писать полностью свой? Зачем мне тратить время на то, что уже реализовано, когда можно взять то что есть и использовать. Давайте напишем свой ЯП, свой компилятор, свою IDE, в конце концов. Зачем нам поделки Microsoft? Но вот они-то как раз в FCL наследование очень широко используют. Они не правы? Бродят в потемках и ждут, когда им откроют глаза на то, как лучше?
0
29.02.2016, 14:20

Не по теме:

Цитата Сообщение от Psilon Посмотреть сообщение
Наследование - достаточно старая концепция, и её придерживаются просто по привычке.
А как-же три кита ООП? )
Наследование - инструмент, и очень удобный. Лично я им пользуюсь когда надо расширить функционал нужного мне класса. Да, далеко не всегда в этом есть необходимость, но заявлять что наследование устарело и им не надо пользоваться как-то неправильно.

0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
29.02.2016, 14:32
Почему? Выходит, если мне нужен свой List<T>, который по многим характеристикам будет отвечать стандартной реализации, но с небольшим изменением, то наследование от стандартного-зло? Писать свой с нуля? Зачем? Тогда наследование вообще не нужно, давайте везде использовать композицию.
И это касается не только приведенного примера, а и всего остального. Возьмем любой контрол, если мне нужно изменить его поведение (не все, а часть) - мне писать полностью свой? Зачем мне тратить время на то, что уже реализовано, когда можно взять то что есть и использовать. Давайте напишем свой ЯП, свой компилятор, свою IDE, в конце концов. Зачем нам поделки Microsoft? Но вот они-то как раз в FCL наследование очень широко используют. Они не правы? Бродят в потемках и ждут, когда им откроют глаза на то, как лучше?
Это не тот случай. Ну вот например - любой одномерный массив наследует IList<T>, но при этом при попытке вызвать 2/3 методов он выбросить эксепшн. Ситуация с переопределением OnDoWork та же - задача методов OnXXX вызывать событие XXX и все. Код, который на это опирается, сломается при ином поведении.

aquaMakc, наследованием чаще злоупотребляют, чем наоборот. Грамотная композиция почти всегда лучше грамотного наследования (см. проблему хрупких базовых классов), вопрос только в поддержке со стороны языка. Ну и да, ООП не панацея Сейчас ООП на вершине, однако кто помнит, когда оно появилось и в каком языке? Правильно, в
Кликните здесь для просмотра всего текста
Smalltalk
, в
Кликните здесь для просмотра всего текста
бородатом конце 70х
. А что тогда было модным? Правильно, Си, фортраны, коболы, что угодно, только не ООП. То, что ООП это круто и приятно стало доходить только десятилетия спустя. Лисп был придуман еще раньше, однако когда в мейнстрим языки начали добавлять функциональные фишки? Лямбды в плюсы только-только добавили, монады появились только в C# 6.0, Pattern Matching только собираются ввести... Популярно != самое лучшее решение. Индустрии свойственна инерция. Это не плохо, но это нужно понимать, и не полагаться на общественное мнение. Изучив сейчас что-то "необычное" из другой области, что через 5 лет станет мейнстримом, можно получить преимущество перед конкурентами в эти же 5 лет, что конечно же прямо скажется на финансовом положении. Не считая общего удовлетворения от собственной "прошаренности", и возможностью похвастаться знаниями перед друзьями. Они же наверняка не отличают функтор от эндофунктора, а зигохистоморфный препроморфизм примут за ругательство
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
29.02.2016, 14:47

Не по теме:

Цитата Сообщение от Psilon Посмотреть сообщение
а зигохистоморфный препроморфизм примут за ругательство
Возьму на вооружение в интернет срачах ))



Любой инструмент надо применять к месту. Если мне надо добавить 1-2 свойства к базовому классу - мне проще воспользоваться наследованием. Если мне надо прокачать логику объекта на основании имеющегося функционала я подумаю об агрегировании.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
29.02.2016, 15:32
aquaMakc, полностью с этим согласен Точно также не стоит лепить ООП из 100500 объектов там, где нужно просто сделать пару функций

Кстати еще немного в тему ругательств. Лишь не так давно начал понимать, о чем они. Хотя сейчас кажется очевидным Котоморфизм вообще отличное слово
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.02.2016, 15:32
Помогаю со студенческими работами здесь

Передача параметра в конструктор
Дамы и господа, нужна помощь! Есть следующий класс с конструктором Tank(int sizeField) using System; using...

Передача в конструктор ссылки на объект
Есть 2 класса Model и Controller, нужно передать в конструктор Controller-а ссылку на Model. Вот так нельзя: public Model...

Наследованием и передача параметров в конструктор
Есть класс Дисциплины public partial class Дисциплины : Form { BindingSource bindingSource; DataSet dataSet; ...

Применение делегатов в качестве обработчиков событий
Реализовать собственное событие (имитация) нажатие клавиш мыши или клавиатуры. Разработать событием на основе стандартного события и...

Применение делегатов в качестве обработчиков событий
Реализовать собственное событие (имитация) нажатие клавиш мыши или клавиатуры. Разработать событием на основе стандартного события и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru