|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Как прикрутить в WinForms приложении INotifyPropertyChanged и реакцию на OnPropertyChanged? Вот МС пример: https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-implement-property-change-notification Код: 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. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45.
Этот пример понятен, но здесь обработчик события в том же классе, а мне надо, чтобы при изменении значения переменной в одном объекте реагировали объекты другого класса. Как такое прикрутить? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 14:38 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Объект который зависит от Person подпишется на его событие и когда событие будет возбуждено выполнится тот метод, который вы добавили к делегату события. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 14:40 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Roman MejtesОбъект который зависит от Person подпишется на его событие и когда событие будет возбуждено выполнится тот метод, который вы добавили к делегату события. ок, это как реализовать: "Объект который зависит от Person подпишется на его событие" ? (в уже существующем приложении) Есть объект другого класса, как сделать его зависимым от Person? Реально у меня в приложении есть класс апп сеттингов, и когда юзер менятем значение какой-то настройки надо чтобы код в другом объекте понимал, что есть изменения и свежее значение перечитывалось ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 15:04 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Код: c# 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 15:14 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
События C# по-человечески: https://habr.com/ru/post/213809/ ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 15:17 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256kнадо чтобы код в другом объекте понималНу так этот другой объект и должен подписываться на события в классе аппсеттингов ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 15:21 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Shocker.ProНу так этот другой объект и должен подписываться на события в классе аппсеттинговТолько надо не забывать отписываться при уничтожении этого "другого объекта", иначе будет утечка памяти. Ну или использовать подходы WeakEvents ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 15:24 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Shocker.Pro256kнадо чтобы код в другом объекте понималНу так этот другой объект и должен подписываться на события в классе аппсеттингов Не совсем понятно зачем в примере выше нужно выводиться из INotifyPropertyChanged, можно и без него создать событие и подписаться на него извне. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 16:24 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
главное помнить один момент когда объект с коротким сроком жизни (объекта А) подписывается на объект срок жизни которого длительный (объект B) К примеру, ваш конфиг, скорее всего статический, по этому все порожденные экземпляры объектов связанные с конфигурацией будут иметь срок жизни, пока ваш процесс выполняется. Подписавшись на событие объекта (B) из объекта (А) в экземпляр делегата объекта (B), сохранится указатель на объект (A). Следовательно, если ваша ссылка на объект (А) будет удалена (вами), она всё еще будет в экземпляре делегата класса (B) и GC не удалит этот объект (A) из памяти. Если таких объектов будет 100500 и они будут то загружаться, то "удаляться", то количество этих объектов будет увеличиваться, а скорость обратного вызова через делегат деградировать. Возникнет "утечка" памяти, так как объект вам уже не нужен, но ссылка на него всё еще существует. Более того вызов события будет приводить к выполнению этого события в класс (А). То есть когда мы из объекта (А) подписываемся на событие объекта (B), мы просто сохраняем в поле типа делегат объекта (B) ссылку на метод который необходимо запустить и ссылку на сам этот объект (чтоб можно было передать аргумент this). ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 16:58 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Roman Mejtesглавное помнить один момент когда объект с коротким сроком жизни (объекта А) подписывается на объект срок жизни которого длительный (объект B) К примеру, ваш конфиг, скорее всего статический, по этому все порожденные экземпляры объектов связанные с конфигурацией будут иметь срок жизни, пока ваш процесс выполняется. Подписавшись на событие объекта (B) из объекта (А) в экземпляр делегата объекта (B), сохранится указатель на объект (A). Следовательно, если ваша ссылка на объект (А) будет удалена (вами), она всё еще будет в экземпляре делегата класса (B) и GC не удалит этот объект (A) из памяти. Если таких объектов будет 100500 и они будут то загружаться, то "удаляться", то количество этих объектов будет увеличиваться, а скорость обратного вызова через делегат деградировать. Возникнет "утечка" памяти, так как объект вам уже не нужен, но ссылка на него всё еще существует. Более того вызов события будет приводить к выполнению этого события в класс (А). То есть когда мы из объекта (А) подписываемся на событие объекта (B), мы просто сохраняем в поле типа делегат объекта (B) ссылку на метод который необходимо запустить и ссылку на сам этот объект (чтоб можно было передать аргумент this). Лайкнул, спасибо ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:07 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256kНе совсем понятно зачем в примере выше нужно выводиться из INotifyPropertyChanged, можно и без него создать событие и подписаться на него извне.Хм. Перепроверил автора топика - так это ж ты и предложил INotifyPropertyChanged. Просто INotifyPropertyChanged - это паттерн. Если он тебе не нужен - ну значит не нужен. Смысл есть, когда один обработчик обрабатывает много разных событий многих разнотипных объектов. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:13 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256kINotifyPropertyChangedэто событие для биндинга обычно. А для своих дел можно использовать хоть MyEvent. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:16 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Roman Mejtes, Если коротко, то нужно отписываться, т.к.сборщик мусора это не умеет. Что отписываться выше говорилось. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:18 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Лично я сделал себе централизованный уведомитель для подобных целей, уведомления уровня приложения. Уведомитель-синглтон принимает от желающих подписки на определенные события, другие желающие могут их возбуждать. Соответственно, реализовано через слабосвязанные события, так что отписка не требуется ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:35 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Shocker.ProУведомитель-синглтона если в главной форме? И достать всегда можно. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:37 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Petro123а если в главной форме? И достать всегда можно.да без разницы ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:38 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Shocker.Pro256kНе совсем понятно зачем в примере выше нужно выводиться из INotifyPropertyChanged, можно и без него создать событие и подписаться на него извне.Хм. Перепроверил автора топика - так это ж ты и предложил INotifyPropertyChanged. Просто INotifyPropertyChanged - это паттерн. Если он тебе не нужен - ну значит не нужен. Смысл есть, когда один обработчик обрабатывает много разных событий многих разнотипных объектов. Да не я, это у майкрософта написано ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 18:12 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Petro123256kINotifyPropertyChangedэто событие для биндинга обычно. А для своих дел можно использовать хоть MyEvent. Спасибо, Пэдро, теперь понял ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 18:13 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256kНе совсем понятно зачем в примере выше нужно выводиться из INotifyPropertyChanged, можно и без него создать событие и подписаться на него извне. 256k Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9.
Большинство стандартных контролов умеют "правильно реагировать" на соответствующее событие подвязанного источника данных (см. binding). Т.е., разработчику не нужно "вручную" разруливать событие из другого потока, выставлять свойства контрола в соответствие новому значению, отписываться от события и т.п. Типа, создал связь (binding) с источником данных - и забыл, примерно для этого. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 18:22 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Roman Mejtesглавное помнить один момент когда объект с коротким сроком жизни (объекта А) подписывается на объект срок жизни которого длительный (объект B) К примеру, ваш конфиг, скорее всего статический, по этому все порожденные экземпляры объектов связанные с конфигурацией будут иметь срок жизни, пока ваш процесс выполняется. Подписавшись на событие объекта (B) из объекта (А) в экземпляр делегата объекта (B), сохранится указатель на объект (A). Следовательно, если ваша ссылка на объект (А) будет удалена (вами), она всё еще будет в экземпляре делегата класса (B) и GC не удалит этот объект (A) из памяти. Если таких объектов будет 100500 и они будут то загружаться, то "удаляться", то количество этих объектов будет увеличиваться, а скорость обратного вызова через делегат деградировать. Возникнет "утечка" памяти, так как объект вам уже не нужен, но ссылка на него всё еще существует. Более того вызов события будет приводить к выполнению этого события в класс (А). То есть когда мы из объекта (А) подписываемся на событие объекта (B), мы просто сохраняем в поле типа делегат объекта (B) ссылку на метод который необходимо запустить и ссылку на сам этот объект (чтоб можно было передать аргумент this). Кстати, а как бы отписать всех обработчиков? т.е. я могу не знать кто уже подписался и сколько подписчиков, но знаю, что пора "делать ноги". ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 12:58 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256k, При закрытии приложения не надо отписывать. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 13:08 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256kКстати, а как бы отписать всех обработчиков? т.е. я могу не знать кто уже подписался и сколько подписчиков, но знаю, что пора "делать ноги".Если предполагается уничтожить экземпляр класса, НА события которого кто-то подписался, то ничего страшного, он уничтожится, так как на него ссылок нет, это наоборот - он содержит ссылки на подписчиков. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 13:17 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256k, Для начала, стоит задать вопрос, что такое событие? Событие по своей сути очень похоже на Свойство класса, это надстройка над полем класса, позволяющая добавить уровень абстракции. Свойство реализуется 2 методами Get и Set над полем класса заданного типа. Событие реализуется 2 методами Add и Remove, а в качество поля используется делегат заданного типа. В обоих случая мы можем не определять реализацию методов свойства или события явно, за нас это делает компилятор. по этому будет достаточно написать: Код: c# 1.
Всё остальное за нас сделает компилятор, в результате его работы получится, нечто похожее на то, что написано ниже. Но если реализация объявлена явно, мы можем добавить свой код, к примеру, код проверки значения свойства или проверки объекта который пытается подписаться на наше событие. По факту мы можем сделать так, что подписываясь на событие, объекту будет в этом отказано и ссылка которую он передает на метод и объект не будет добавлена в делегат, или будет добавлена сразу в 2, а возможно я создам таблицу, в которой буду хранить все объекты, которые добавлены в делегате. Вариантов море. Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
Поле типа делегат это объект ссылочный тип похожий на список, в нём хранятся ссылки на методы и если мы добавляем в делегат метод экземпляра объекта, ссылка на этот объект. Удалив делегат, обнулив его, мы потеряем все указатели на эти объекты и методы, а через какое то время GC грохнет этот объект и все те объекты, на которые он ссылается, так как все они больше не имеют корневого объекта Код: 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. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100.
Результат выполнения: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Всё это довольно просто и весело, когда вы работаете в 1 потоке, но когда приложение многопоточное, наступает жопа, так как добавление обработчика события операция не атомарная (мягко говоря). По этому, в тот момент, когда объект подписывается или отписывается на событие, оно может быть возбуждено. Если объект отписывается, он может быть уже не готов его обработать, но ссылка в делегате всё еще существует, такая ситуация может привести к исключению или другим неприятным последствиям. Но это тема для другой темы. если где я не прав, пусть меня поправят, я же не Троелсен :D ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 14:12 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Roman MejtesВсё это довольно просто и весело, когда вы работаете в 1 потоке, но когда приложение многопоточное, наступает жопа, так как добавление обработчика события операция не атомарная (мягко говоря). По этому, в тот момент, когда объект подписывается или отписывается на событие, оно может быть возбуждено. Если объект отписывается, он может быть уже не готов его обработать, но ссылка в делегате всё еще существует, такая ситуация может привести к исключению или другим неприятным последствиям. Но это тема для другой темы. если где я не прав, пусть меня поправят, я же не Троелсен :D Эта проблема подписчика ("он может быть уже не готов его обработать"), по-моему, надуманна (сначала отпишись, затем отключай готовность обрабатывать). А вот "возбуждение" события действительно может быть проблемным. Такая конструкция (беспроблемная) возможна лишь начиная с C#6 Код: c# 1. 2.
а вот такая конструкция очень даже проблемная (потоконезащищенная) Код: c# 1. 2.
... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 14:58 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
LRRoman MejtesВсё это довольно просто и весело, когда вы работаете в 1 потоке, но когда приложение многопоточное, наступает жопа, так как добавление обработчика события операция не атомарная (мягко говоря). По этому, в тот момент, когда объект подписывается или отписывается на событие, оно может быть возбуждено. Если объект отписывается, он может быть уже не готов его обработать, но ссылка в делегате всё еще существует, такая ситуация может привести к исключению или другим неприятным последствиям. Но это тема для другой темы. если где я не прав, пусть меня поправят, я же не Троелсен :D Эта проблема подписчика ("он может быть уже не готов его обработать"), по-моему, надуманна (сначала отпишись, затем отключай готовность обрабатывать). Наверное, речь шла о проблеме #4 вот в этой статье https://www.codeproject.com/Articles/886223/Csharp-Multithreading-and-Events, тогда да, ее нужно решать... ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 15:13 |
|
|
start [/forum/topic.php?fid=20&msg=39762860&tid=1399097]: |
0ms |
get settings: |
8ms |
get forum list: |
11ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
233ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
47ms |
get tp. blocked users: |
1ms |
others: | 304ms |
total: | 621ms |
0 / 0 |