|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
Подскажите пожалуйста, равносильны ли следующие два блока кода, обратить внимание на делегат и смотреть в контексте многопоточного приложения, в первом случае для каждого SocketAsyncEventArgs создается свой делегат, а во втором используется общий, не возникнут ли проблемы с Thread safety: Код: c# 1. 2. 3. 4. 5. 6. 7.
Код: c# 1. 2. 3. 4. 5. 6. 7. 8.
Спасибо за участие и помощь! ... |
|||
:
Нравится:
Не нравится:
|
|||
10.12.2012, 14:42 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
В случае с общим может возникнуть ситуация, что один поток, к примеру изменил/обнулил или еще что. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.12.2012, 16:07 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
АбсолютВ случае с общим может возникнуть ситуация, что один поток, к примеру изменил/обнулил или еще что. Изменить экземпляр делегата не получится, т.к. нет публичного доступа на запись не к чему. Обнулить - это вряд ли, т.к. ссылка на экземпляр остается в инициализирующем классе. Если это все, то получается подводных камней нет. Еще раз спасибо. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.12.2012, 16:23 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
goalinternet, оба варианты экиваваленты с точки зрения многопоточности, но вариант с отдельным делегатом потратит зря чуть больше памяти (~25 Кб в режиме отладки). Ты в данном случае должен позаботиться чтобы _реализация_ метода completeEvent была безопасной с точки зрения многопоточности. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.12.2012, 16:34 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
bazile, Метод потокобезопасен. Спасибо за ответ. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.12.2012, 17:52 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
Не в коем случае никогда не используйте первый случай, такое ощущение что GC высвобождает несколько экземпляров, и я терял сетевые пакеты, после того сделал как описано во втором случае - больше ничего не пропадает. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.12.2012, 12:50 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
goalinternetНе в коем случае никогда не используйте первый случай, такое ощущение что GC высвобождает несколько экземпляров, и я терял сетевые пакеты, после того сделал как описано во втором случае - больше ничего не пропадает. Каюсь я не прав. Обе версии равносильны. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.12.2012, 15:27 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
goalinternetКаюсь я не прав. Обе версии равносильны.ессесна. ну кроме количества памяти , как написал bazile т.к. делегат это некий указатель на метод. а все методы вызываются с дополнительным параметром - контектс вызова ( типа вызывающи класс) Код: c# 1. 2. 3. 4. 5. 6.
... |
|||
:
Нравится:
Не нравится:
|
|||
14.12.2012, 15:56 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
beg-in-er...т.к. делегат это некий указатель на метод. а все методы вызываются с дополнительным параметром - контектс вызова ( типа вызывающи класс) Код: c# 1. 2. 3. 4. 5. 6.
А можно подробностей? ... |
|||
:
Нравится:
Не нравится:
|
|||
14.12.2012, 16:03 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
beg-in-ergoalinternetКаюсь я не прав. Обе версии равносильны.ессесна. ну кроме количества памяти , как написал bazile т.к. делегат это некий указатель на метод. а все методы вызываются с дополнительным параметром - контектс вызова ( типа вызывающи класс) Код: c# 1. 2. 3. 4. 5. 6.
class сгениерит среда если есть замыкание на внешнею переменную, и то не всегда. коды равнозначные, у первого надо учесть только что среда расставит все по своим местам типа EventHandler<SocketAsyncEventArgs> completeEvent=-чтото; saea.Completed += completeEvent; и размер стеека функции у них должен быть одинаковый. единственно что не учел товарищ, ( впрочем не видим этот код и эта тема не поднималась) как он будет исповедовать объект перед смертью, слабыми событиями там даже не пахнет ( я поднял это, если он заговорил о уборщике) ... |
|||
:
Нравится:
Не нравится:
|
|||
14.12.2012, 18:17 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
Lexxxxx А можно подробностей? Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9.
Function2(7); 00000025 mov ecx,dword ptr [ebp-3Ch] 00000028 mov edx,7 0000002d call FF919DC8 Function2(3); 00000033 mov ecx,dword ptr [ebp-3Ch] 00000036 mov edx,3 0000003b call FF919DC8 ptr [ebp-3Ch] это как бэ адресс класса ... |
|||
:
Нравится:
Не нравится:
|
|||
14.12.2012, 19:16 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
И все таки я нифига не понял! Получается что можно сослаться на один и тот же экземпляр метода в качестве обработчика события в двух разных потоках и при этом совершенно не нужно заботится о потокобезопасности этого метода?! ... |
|||
:
Нравится:
Не нравится:
|
|||
14.12.2012, 21:14 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
Lexxxxx, о потокобезопасности захваченного объекта, надо заботиться, одна из отличительных особенностей делегата, это то что метод может исолниться когда ему вздумается ( образно) пользователь нажал кнопку по своему разумению? и по этому вся работа с замыканием ложится на Вас. предположим нажали кнопку, и пошол грид дербаниться ( долго)( грид замыкание) а в это время еще нарисовался делегат с этим же методом, он тоже полез дербанить грид ( в простонародье это называется двухстволка) но там то мы хоть можем договориться куда совать, а с гридом нет, по этому и озвучили эту тему. хоть и компилятор создает класс обертку для функции под делегат, и включает в этот класс объект замыкание, но при создании этой обертки он инициализирует этот объект обетом снаружи (grid) ... |
|||
:
Нравится:
Не нравится:
|
|||
14.12.2012, 21:37 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
Где-то в степи, На сколько я понимаю, если один и тот же метод повесить обработчиком на пару или более событий в разных потоках, может случится одновременный вызов и/или переключение контекста потоков один или более раз, а значит внутри метода с его данными может случится просто фарш. А значит или тело этого метода должно быть полностью обернуто в lock, что приведет к ожиданию других потоков, а значит к потере быстродействия, или просто нужно для каждого потока иметь свой экземпляр метода-обработчика чтобы не иметь потерь при блокировках потоков при одновременном наступлении события в нескольких из них. Правильно я рассуждаю? ... |
|||
:
Нравится:
Не нравится:
|
|||
14.12.2012, 22:16 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
LexxxxxПравильно я рассуждаю? нет. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.12.2012, 23:27 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
Lexxxxx, нет конечно Вы же можете инициализировать делегат статическим методом, там то что будет в нутрях изменяться, равнозначно и можно инициализировать методом экземпляра объекта, каждый поток получит делегат, и при вызове получит метод в первозданном виде, можно зарядить делегат по месту. вот пример var table = new DataTable(); table.Columns.Add("1"); table.Columns.Add("2"); new Thread(() => table.Rows.Add("asa", "sad")).Start(); я в какой то функции исполнил такой код; Создал таблицу, зарядил ее колонками, и вызвал поток зарядив его делегатом по месту () => table.Rows.Add("asa", "sad") в этом делегате я сделал замыкание на таблицу то биш в нее вставляю строку. я уверен что я вставил 1 строку, но в это время другой поток, проснулся и полез тоже вставлять строку, вот я и в ах..е, как так я вставил строку, а там уже 2 ((... поаял а не? зы кстати если посмотреть байт код из примера, там должен класс обертка конкретно создаться, и положиться в стек.. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.12.2012, 23:47 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
Lexxxxx, "потокобезопасность" - проблема достаточно деликатная/мутная, ее нельзя решить раз и навсегда какими-то простыми правилами "либо-либо", необходим достаточный уровень понимания того что будет происходить (как будет выполняться код) в каждом конкретном случае... вот частоприводимый по теме простой пример: Код: 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2012, 01:02 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
Где-то в степи...Создал таблицу, зарядил ее колонками, и вызвал поток зарядив его делегатом по месту () => table.Rows.Add("asa", "sad") в этом делегате я сделал замыкание на таблицу то биш в нее вставляю строку. я уверен что я вставил 1 строку, но в это время другой поток, проснулся и полез тоже вставлять строку, вот я и в ах..е, как так я вставил строку, а там уже 2 ((... поаял а не?.. Как я понял экземпляр таблицы один для всех делегатов во всех потоках? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2012, 09:38 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
LR, Не могли бы Вы разъяснить подробно этот пример для неграмотных? Уже не совсем понятно почему в первом цикле выводимые номера дублируются? ) То, что они выводятся не по порядку вроде как объясняется тем, что планировщик задач запускает потоки по своему усмотрению и не обязательно в том порядке, в котором их ему передавали. Но откуда повторения?! ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2012, 10:16 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
LexxxxxГде-то в степи...Создал таблицу, зарядил ее колонками, и вызвал поток зарядив его делегатом по месту () => table.Rows.Add("asa", "sad") в этом делегате я сделал замыкание на таблицу то биш в нее вставляю строку. я уверен что я вставил 1 строку, но в это время другой поток, проснулся и полез тоже вставлять строку, вот я и в ах..е, как так я вставил строку, а там уже 2 ((... поаял а не?.. Как я понял экземпляр таблицы один для всех делегатов во всех потоках? Ну да, д. это по существу код потока,( мы создаем поток спуская в него делегат, запускаем делегат begininvoke) и естественно должны рассматривать этот код с позиции потока аки конкурентный доступ, к чему то общему для потоков, или коллизии при исполнении и т.д. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2012, 10:53 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
Где-то в степиНу да, д. это по существу код потока,( мы создаем поток спуская в него делегат, запускаем делегат begininvoke) и естественно должны рассматривать этот код с позиции потока аки конкурентный доступ, к чему то общему для потоков, или коллизии при исполнении и т.д. Ну так я же об этом и говорил, а Вы сказали что я не прав. А Вы не подскажете ответ на вопрос про дублирующиеся номера? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2012, 11:10 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
Lexxxxx может случится одновременный вызов и/или переключение контекста потоков один или более раз, а значит внутри метода с его данными может случится просто фарш. А значит или тело этого метода должно быть полностью обернуто в lock, ну конечно не прав, какие переключения контекстов в методе? какой фарш может быть с данными метода, если это переменные var в методе, и с внешней средой они не контактируют. зачем лок на все тело, если тело с внешней средой кода вообще не завязано, равно не завязано, ни с какими объектами окружающих метод, не контактирует и не ссылается на них. Даже принятия решения лок по отношению к внешней переменной ( переменной замыкания) должно быть обосновано в плане логики. если например предположить что это какой то аккумулятор типа value, работающий атомарно, зачем там лок вообще нужен? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2012, 11:37 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
что то я забыл про вопрос. Есть классика в сети обязательно почитать всем и разобраться http://www.rsdn.ru/article/dotnet/CSThreading1.xml http://www.rsdn.ru/article/dotnet/CSThreading2.xml ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2012, 11:44 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
Где-то в степи, Да, похоже я неправильно выразился. Каждый поток имеет свой стек, поэтому локальные переменные метода для каждого потока свои. Но вот данные, переданные в метод, тот же экземпляр таблицы, могут быть превращены в месиво, или нет, что конечно же зависит от того, что именно происходит в этом методе. Прочитать и разобраться конечно можно, но хотелось "проскочить на халяву". ) Там еще и третья часть есть http://rsdn.ru/article/dotnet/Threading_In_C_Sharp_Part_3.xml ... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2012, 11:50 |
|
Можно ли использовать один делегат для событий из разных потоков?
|
|||
---|---|---|---|
#18+
EAP давно уже на свалке вместо него другая модель асинхронности. Код: 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
15.12.2012, 13:17 |
|
|
start [/forum/topic.php?fid=20&msg=38080444&tid=1405497]: |
0ms |
get settings: |
10ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
62ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
61ms |
get tp. blocked users: |
1ms |
others: | 12ms |
total: | 181ms |
0 / 0 |