Что? Нет. Эти две величины вообще между собой не связаны. Количество операций в секунду это ограничение, выставленное мной для барьера, а количество потоков относится к тестовому методу. Метод запускает проверку на 4х потоках.
И да, 6х4=24 :)
Мы пользуемся DevExpress. Жутко тормозная штука. К тому же писались контролы явно для винформ, а потом портировались под WPF «как есть». Про MVVM они слышали краем уха. Короче все, за что их покупают — это обертка. А внутри какашка. Полагаю, что Telerik не сильно отличаются в этом плане. Контролы, написанные мной, работают в разы быстрее.
А что касается поддержки, я еще не встречал настолько гибкой системы. Это тот случай, когда допиливать новые фичи могут сами .net разработчики, и они не будут костылями.
Если вам не хочется, чтобы обработчик повесил работу класса, то напишите такой обработчик — это нетрудно.
Генератор события написал я, а обработчик будет делать Вася Пупкин, который ничего не знает про логику работы моего генератора. поэтому, если обработчик будет работать в одном потоке с логикой генератора, это как раз и поставит разработчика в рамки.
Вот я и говорю что вы сами не понимаете что говорите.
Круто, а какие-то основания для этих утверждений у вас есть? Потому что «создать экземпляр класса Thread и сказать ему Start» — это и есть создание нового потока.
Поток при этом не создается. Потоками пул управляет, а не пользователь. После команды старт происходит запрос на запуск потока (или как то так). Я могу стартануть 400 экземпляров Thread, но реально работать будут при этом только 4 из них (на моем железе и среде).
Это если у вас fire-and-forget, что далеко не для всех событий верно. А вы это почему-то считаете поведением по умолчанию.
Ничего не слышал про fire-and-forget для системы событий в .net. Гугл не помог. Подскажите где почитать, потому что в данный момент мне это кажется плохой архитектурой а не особым подходом.
Да нет же. Нельзя кинуть потоки в пул.
Беда с терминологие, походу… я создал 400 экземпляров Thread и сказал им старт.
Отнюдь. Я обсуждаю ваш конкретный код.
Пример с потоками абстрактный… мне, может, нужно было его на псевдо языке написать, чтобы это было понятно?
Если нас не учили, это не значит, что я не учил. Я говорю про других людей. Опять же я не все знаю и понимаю, но дальше своих знаний я в этой статье не лез. Почти все что тут назвали ошибками является обычной абстракцией (остальное я уже поправил), но я не могу этого объяснить. Слово абстрактный им не знакомо или хотят блеснуть знаниями я не знаю…
Нет, вы написали «BeginInvoke порождает новый поток». Это не абстракция, это конкретное — и ложное — утверждение.
… вот только в статье нет ни слова о том, что делегат будет выполнен на пуле. Более того, явно написано, что будет порожден новый поток.
Затем, чтобы (а) вы не понимаете, что неправильно работете с потоками и (б) я не хочу видеть пример неправильной работы с потоками.
Это как раз пример того, что вы не понимаете происходящего. Сделав 400 BeginInvoke вы не потребовали от системы генерацию 400 потоков.
Класс Thread в принципе не является потоком. Это обертка. Абстракция.
Говоря поток, я имею ввиду Thread. Говоря «порождает» поток, я имею ввиду создает Thread и дает ему команду «Пуск». Так вот, одновременно (почти) создаются 400 экземпляров Thread. Когда они будут выполняться, генератору событий не важно. Ему даже не важно, будут ли они вообще выполняться, или лягут с ошибкой. Обработка событий не входит в его компетенцию. Вы со своими заумными фразами про потоки забыли про принципы ООП!
Теперь что касается этих 400 потоков. Да, я просто кинул их бездумно в пул. Ну так мне не важно, как, когда и в каком порядке они будут выполняться и программа больше ничего не делает. Я не могу в этом случае рассмотреть каждый случай отдельно, поэтому ПРАВИЛЬНОГО решения тут нет и быть не может! Для случая, когда потребуется соблюдать порядок, я создам очередь из задач (или шелдер). Для случая, когда выполнение других потоков будет важнее, я укажу приоритет для этих событий ниже. Зато, если я не вынесу порождение событий в отдельный от воркера поток, мне придется снижать приоритет всего воркера по отношению к другим потокам. Но это уже тема не для джуниоров и я не стал включать это все в статью!
А вы тут обсуждаете абстрактного коня в вакууме, и при этом ругаетесь на моего коня. Мой конь круче!
Может. Точнее имеет возможность. Это уже вопрос реализации. У IObserver нет метода Subscribe. А это значит что способ подписки остается на усмотрение программиста.
Так это не вопрос работы с потоками, это вопрос работы с делегатами. И это описано в любой книжке про C# и/или CLR.
Но статья не про потоки или делегаты!
Потому что BeginInvoke на делегате выбрасывает делегат в тредпул, а не в новый поток. Со всеми занятными вытекающими.
Вы лезете в дебри. Возьмите 200 ядер и ваши потоки выполнятся в раз.
… и вы серьезно считаете, что создавать 200 потоков во время вызова события — это нормально? То, что в этот момент вы съели (при настройках по умолчанию) 200мб памяти, вас не смущает?
Нет я так не считаю, я уже написал об этом раз 10.
К тому, что вы сам, похоже, не понимаете, как работает предлагаемое вами решение.
В работе с потоками я прикрылся за абстракциями. Мне не важно, как отработает пул. Мне важны 2 вещи:
1. Обработчики будут выполняться параллельно (да, на самом деле все не совсем так и одновременных потоков будет по количеству ядер, свободной памяти и тд, но я не раскрываю данную абстракцию в этой статье. Именно поэтому я и говорю, что для вашего примера потоков будет 400, ведь я потребовал от системы генерацию 400 потоков)
2. Породитель событий не будет дожидаться их выполнение и продолжит свою работу.
Зачем вы пытаетесь мне сказать, что я неправильно работаю с потоками, если я в начале статьи сказал, что я неправильно с ними работаю и статья не о них?
Да не продвигаю я в статье никакой подход. Я только на конкретном примере показываю, как все это работает. Прочитав данную статью, человек, который никогда не задумывался о том, где выполняются обработчики событий, должен это понять. А как использовать это знание — уже его дело.
Знаете, людям, которым неочевидно, в каком потоке вызывается делегат, надо идти обратно учиться. Простите за прямоту.
Согласен. Нас вот в универе не учили работе с потоками. Выходит, приходится заниматься самообразованием. Для этого есть курсы, книги и подобные статьи.
Вот только это неправильный ответ.
Я повторю свой пример: вот у нас есть событие, на него подписано двести обработчиков. Мы дважды вызвали это событие. Сколько потоков будет создано?
Почему не правильный то?
Количество потоков будет равно Количеству подписчиков умноженному на количество вызовов. В случае с вашими цифрами их будет 400.
Да, да и еще раз да! Я устал отвечать на одни и те же замечания. Статья не об организации потоков, она просто рассказывает о том, в каких потоках выполняются события. Не все об этом знают. Это для джуниоров. Про организацию потоков я ничего не писал. Для этого одной статьи просто может не хватить из-за количества вариаций.
И да, 6х4=24 :)
Шикарное окончание поста :)
В статье написано, что сервис автоматический. То есть собак спускал не владелец сервиса, а робот, когда в него опускали монетку
Детей усыновить можно. Хорошая мотивация, кстати.
Мы пользуемся DevExpress. Жутко тормозная штука. К тому же писались контролы явно для винформ, а потом портировались под WPF «как есть». Про MVVM они слышали краем уха. Короче все, за что их покупают — это обертка. А внутри какашка. Полагаю, что Telerik не сильно отличаются в этом плане. Контролы, написанные мной, работают в разы быстрее.
А что касается поддержки, я еще не встречал настолько гибкой системы. Это тот случай, когда допиливать новые фичи могут сами .net разработчики, и они не будут костылями.
Поток при этом не создается. Потоками пул управляет, а не пользователь. После команды старт происходит запрос на запуск потока (или как то так). Я могу стартануть 400 экземпляров Thread, но реально работать будут при этом только 4 из них (на моем железе и среде).
Ничего не слышал про fire-and-forget для системы событий в .net. Гугл не помог. Подскажите где почитать, потому что в данный момент мне это кажется плохой архитектурой а не особым подходом.
Беда с терминологие, походу… я создал 400 экземпляров Thread и сказал им старт.
Пример с потоками абстрактный… мне, может, нужно было его на псевдо языке написать, чтобы это было понятно?
Так разберитесь с ними сами прежде всего.
Класс Thread в принципе не является потоком. Это обертка. Абстракция.
Говоря поток, я имею ввиду Thread. Говоря «порождает» поток, я имею ввиду создает Thread и дает ему команду «Пуск». Так вот, одновременно (почти) создаются 400 экземпляров Thread. Когда они будут выполняться, генератору событий не важно. Ему даже не важно, будут ли они вообще выполняться, или лягут с ошибкой. Обработка событий не входит в его компетенцию. Вы со своими заумными фразами про потоки забыли про принципы ООП!
Теперь что касается этих 400 потоков. Да, я просто кинул их бездумно в пул. Ну так мне не важно, как, когда и в каком порядке они будут выполняться и программа больше ничего не делает. Я не могу в этом случае рассмотреть каждый случай отдельно, поэтому ПРАВИЛЬНОГО решения тут нет и быть не может! Для случая, когда потребуется соблюдать порядок, я создам очередь из задач (или шелдер). Для случая, когда выполнение других потоков будет важнее, я укажу приоритет для этих событий ниже. Зато, если я не вынесу порождение событий в отдельный от воркера поток, мне придется снижать приоритет всего воркера по отношению к другим потокам. Но это уже тема не для джуниоров и я не стал включать это все в статью!
А вы тут обсуждаете абстрактного коня в вакууме, и при этом ругаетесь на моего коня. Мой конь круче!
Но статья не про потоки или делегаты!
Вы лезете в дебри. Возьмите 200 ядер и ваши потоки выполнятся в раз.
Нет я так не считаю, я уже написал об этом раз 10.
В работе с потоками я прикрылся за абстракциями. Мне не важно, как отработает пул. Мне важны 2 вещи:
1. Обработчики будут выполняться параллельно (да, на самом деле все не совсем так и одновременных потоков будет по количеству ядер, свободной памяти и тд, но я не раскрываю данную абстракцию в этой статье. Именно поэтому я и говорю, что для вашего примера потоков будет 400, ведь я потребовал от системы генерацию 400 потоков)
2. Породитель событий не будет дожидаться их выполнение и продолжит свою работу.
Зачем вы пытаетесь мне сказать, что я неправильно работаю с потоками, если я в начале статьи сказал, что я неправильно с ними работаю и статья не о них?
Почему не правильный то?
Количество потоков будет равно Количеству подписчиков умноженному на количество вызовов. В случае с вашими цифрами их будет 400.
Но к чему вообще этот вопрос?