пятница, 10 июня 2016 г.

Немасштабируемый вэб сервер IIS - откуда он берется ?

Плохая архитектура


Представим себе что мы написали ASP.NET или WCF приложение без использования асинхронных операций - что произойдет ?

При попытке коннекта от клиента IIS создаст в ThreadPool новый поток, который создаст запрос к базе данных и ЗАБЛОКИРУЕТСЯ ожидая ответа ! В случае с высокой загрузкой сервера, когда блокировки будут возникать быстрее чем база данных отдавать ответы разблокируя поток - число заблокированных потоков будет расти.


Но что самое главное - у этого роста есть четкий предел: -лишь  определенное количество потоков поток ThreadPool сможет создать,  и наступит момент когда система выдаст OutOfMemory Exception ! И данное исключение не может быть обработано - так как исключение возникает в самом ThreadPool и наш код в этот момент находиться в стеке.

То есть что произойдет - процесс сервера будет уничтожен (TerminateProcess) вместе со всеми потоками, но как только первый же клиент создаст запрос - процесс создастся вновь автоматически, и все опять пойдет по кругу !

Возникает "магия" - вдруг ни с того ни с сего клиенты не получают ответов (периодически), но потом все работает как обычно ...

суббота, 4 июня 2016 г.

Контексты исполнения (ExecutionContext) и синхронизации (SynchronizationContext) - что это такое и с чем их едят ?

Контекст исполнения (ExecutionContext) 


Если коротко - это некие "внешние данные", причем они подобны воздуху - мы его не замечаем пока его используем, но его отсутствие смерти подобно ! Обычно это данные по правам и доступам (Principal), данные аутентификации и т.д. и т.п. Сам же ExecutionContext -  это просто контейнер для данных.
Причина его появления понятна и ясна - если в синхронном мире у нас есть только один поток и данные не изменны , то в асинхронном нам надо знать а где мы вообще в данный момент времени .

пятница, 3 июня 2016 г.

Особенности await в WinForms

Если попытаться запустить await функцию из из основного потока WinForms - то ничего не получиться - все скомпилируется, вызовется до await, после чего управление как и положено вернется в основной поток, но так как это не совсем простой поток - а основной поток GUI  у которого имеется SynchronizationContext - то await поток обратного вызова который рассматривался в предыдущем посте никогда не получит управления и приложение "зависнет":



четверг, 2 июня 2016 г.

Ограничения для Async - где нельзя применять !



Async применять нельзя в/для :

  • функции - точке входа программы ( функция Main не может быть async)
  • конструкторе класса, property get/set методы, и методы для event add/remove
  • функции с параметрами out / ref
  • никаких await в catch, finally и unsafe блоках ( начиная с C# 6 - можно в catch, finally )
  • также нельзя использовать в блокировках lock или Monitor Enter/Exit
    • вместо этого используйте SemaphoreSlim.WaitAsync
  • в запросах (например linq) await можно использовать только
    • в первой коллекции from или join

Асинхронные функции C# - как работает await/async

Префикс await по сути своей создает отдельный поток (№13 в нашем случае), который ставиться в пул CLR и ожидает когда основной поток ( №10) передаст ему управление: