Forwarded from devdigest // dot net
Асинхронная обработка длительных задач в ASP.NET Core
https://blog.elmah.io/async-processing-of-long-running-tasks-in-asp-net-core
#async #asonet #aspnetcore
https://blog.elmah.io/async-processing-of-long-running-tasks-in-asp-net-core
#async #asonet #aspnetcore
elmah.io Blog - .NET Technical tutorials/guides and new features
Async processing of long-running tasks in ASP.NET Core
In this post, I'll show you how to implement async processing in ASP.NET Core, using a queue and the Background Worker feature.
Forwarded from devdigest // dot net
Основные виды архитектуры веб-приложений
https://docs.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/common-web-application-architectures
#software #architecture #aspnet
https://docs.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/common-web-application-architectures
#software #architecture #aspnet
Docs
Common web application architectures - .NET
Architect Modern Web Applications with ASP.NET Core and Azure | Explore the common web application architectures
Forwarded from razumovsky r
на выходе будет что то такое
https://github.com/smartstore/SmartStoreNET/blob/4.x/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs
https://github.com/smartstore/SmartStoreNET/blob/4.x/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs
GitHub
SmartStoreNET/src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs at 4.x · smartstore/SmartStoreNET
Open Source ASP.NET MVC Enterprise eCommerce Shopping Cart Solution - smartstore/SmartStoreNET
Forwarded from devdigest // dot net
Взгляд на recod изнутри: декомпиляция в plain C#
https://garywoodfine.com/c-records-the-good-bad-ugly
#net6 #record #records
https://garywoodfine.com/c-records-the-good-bad-ugly
#net6 #record #records
Garywoodfine
C# Records - The good, bad & ugly | Gary Woodfine
C# 9.0 introduces record types, a reference type that provides synthesized methods to provide value semantics for equality. Dive in deeper to understand what this means
https://github.com/bchavez/Bogus
полезная утилита для генерации фейковых данных. Будет полезна для тестов
полезная утилита для генерации фейковых данных. Будет полезна для тестов
GitHub
GitHub - bchavez/Bogus: :card_index: A simple fake data generator for C#, F#, and VB.NET. Based on and ported from the famed faker.js.
:card_index: A simple fake data generator for C#, F#, and VB.NET. Based on and ported from the famed faker.js. - bchavez/Bogus
Лично я считаю, что за программирование на WPF,а тем более на WinForms надо давать бесплатно молоко
Forwarded from devdigest // dot net
Несмотря на то, что Microsoft активно развивает WPF и MAUI, Windows Forms не ушел в историю. В статье вы узнаете, что нового появилось Windows Forms с выходом .NET 6
https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-in-net-6-0/
#WindowsForms #windows #forms #UI #net6
https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-in-net-6-0/
#WindowsForms #windows #forms #UI #net6
Microsoft News
What’s new in Windows Forms in .NET 6.0
Read about the new features that are in Windows Forms in .NET 6.0.
Forwarded from .NET Разработчик
День шестьсот седьмой. #ЗаметкиНаПолях
Паттерн Options. Начало
Паттерн Options помогает связывать конфигурацию приложения со строго типизированными классами. Преимущество этого подхода перед получением каждого свойства конфигурации по отдельности (помимо сокращения объёма кода) в том, что есть возможность группировать связанные свойства, а также производить валидацию свойств.
Что если нам нужно обновлять значения параметров во время работы приложения?
В этом случае вместо
1. IOptionsSnapshot<T>
Поддерживает перезагрузку параметров и именованные параметры. Регистрируется как Scoped сервис. Поэтому обновлённые значения параметров будут доступны при следующем запросе к приложению. Однако из-за регистрации как Scoped,
2. IOptionsMonitor<T>
Поддерживает перезагрузку параметров и именованные параметры. Регистрируется как Singleton сервис. Значения параметров доступны через
Продолжение следует…
Источник: https://app.pluralsight.com/library/courses/dotnet-core-aspnet-core-configuration-options/
Паттерн Options. Начало
Паттерн Options помогает связывать конфигурацию приложения со строго типизированными классами. Преимущество этого подхода перед получением каждого свойства конфигурации по отдельности (помимо сокращения объёма кода) в том, что есть возможность группировать связанные свойства, а также производить валидацию свойств.
"Position": {Заметьте, что используется статическая переменная Position с путём к секции конфигурации (в данном случае
"Title": "Editor",
"Name": "Joe Smith"
}
public class PositionOptions {
public const string Position = "Position";
public string Title { get; set; }
public string Name { get; set; }
}
"Position"
), чтобы избежать опечаток (см. ниже). Получить значение в коде можно через внедрение зависимости IConfiguration
:private readonly IConfiguration _configuration;Далее либо через вызов метода
ConfigurationBinder.Bind
:var positionOptions = new PositionOptions(); _configuration.GetSection(PositionOptions.Position)либо через вызов метода
.Bind(positionOptions);
ConfigurationBinder.Get<T>
:positionOptions =
_configuration.GetSection(PositionOptions.Position)
.Get<PositionOptions>();
Кроме того, можно добавить регистрацию параметров в сервисы:public void ConfigureServices(IServiceCollection services) {И использовать через внедрение зависимости:
services.Configure<PositionOptions>(
Configuration.GetSection(
PositionOptions.Position));
// либо
services.AddOptions<PositionOptions>()
.Bind(Configuration.GetSection(
PositionOptions.Position));
…
}
private readonly PositionOptions _options;Обновление значений
public TestModel(IOptions<PositionOptions> options) {
_options = options.Value;
}
Что если нам нужно обновлять значения параметров во время работы приложения?
IOptions<T>
устанавливается как Singleton в контейнере DI. Значения параметров устанавливаются при первом обращении к ним, и не могут быть изменены без рестарта. Именованные параметры (о них далее) не поддерживаются.В этом случае вместо
IOptions<T>
можно использовать один из двух вариантов:1. IOptionsSnapshot<T>
Поддерживает перезагрузку параметров и именованные параметры. Регистрируется как Scoped сервис. Поэтому обновлённые значения параметров будут доступны при следующем запросе к приложению. Однако из-за регистрации как Scoped,
IOptionsSnapshot<T>
не может быть внедрён в Singleton сервисы.2. IOptionsMonitor<T>
Поддерживает перезагрузку параметров и именованные параметры. Регистрируется как Singleton сервис. Значения параметров доступны через
options.CurrentValue
(в отличие от Value
в предыдущих случаях). Кроме того, поддерживается метод OnChange
, в котором регистрируется делегат, обновляющий значения в коде при изменении конфигурации, а также, например, делающий запись в лог.Продолжение следует…
Источник: https://app.pluralsight.com/library/courses/dotnet-core-aspnet-core-configuration-options/
Forwarded from .NET epeshk blog
Monitor
Конструкция
Но класс
Happy path
Метод
В библиотеке Serilog.Sinks.RawConsole я использовал
В итоге, рендеринг лог-сообщений в текст/json выполняется параллельно, с дополнительным бонусом в виде отсутствия копирования, если конкуренции нет (повезло, или используется асинхронная обёртка Serilog.Sinks.Async, Serilog.Sinks.Background)
Также
Сигналы
Кроме блокировок, класс
Чтобы это сделать, вначале нужно захватить lock на объекте.
Затем, вызвав метод
Другой поток может вызвать
Пример с двумя потоками:
Результат:
Пример с N потоками и M сигналами остаётся на самостоятельное изучение
Такой способ передачи сигналов я использовал в библиотеке Serilog.Sinks.Background для того, чтобы сигнализировать background-поток о появлении новых лог-сообщений. Но, с дополнительными доработками:
- логирующие потоки не ждут на локе друг друга — они выбирают, какой пойдёт сигнализировать через
- один log event не активирует background-поток — нужно, чтобы в очереди набралось некоторое их количество
- на случай, если логов мало — background-поток активируется по таймауту. В итоге при отладке и выводе логов в консоль — они появляются на экране почти мгновенно, в 60 ФПС (дальше зависит от того, как быстро рендерит терминал)
Однако, такой способ очень рискованный — если никакой поток не вызвал
Метрики
Через свойство
@epeshkblog | Поддержать канал
█░░░░░░░░░░░░ 28 / 300
Конструкция
lock (obj) { /* do something */ }
в C# — синтаксический сахар для методов класса Monitor
:Monitor.Enter(obj);
try
{
// do something
}
finally
{
Monitor.Exit(obj);
}
Но класс
Monitor
— самодостаточный. Его использование напрямую, без конструкции lock
позволяет реализовать несколько интересных механик.Happy path
Метод
Monitor.TryEnter
позволяет зайти в критическую секцию, если она свободна от других потоков. Можно сделать разную логику в зависимости от того, есть ли конкуренция с другими потоками.В библиотеке Serilog.Sinks.RawConsole я использовал
TryEnter
, чтобы реализовать следующую логику — если конкуренции нет, то log event рендерится в текст/json под локом, сразу в общий буфер. Если не повезло и лок занят — рендеринг текста происходит в локальный для потока буфер, затем берётся лок и результат копируется в общий буфер.В итоге, рендеринг лог-сообщений в текст/json выполняется параллельно, с дополнительным бонусом в виде отсутствия копирования, если конкуренции нет (повезло, или используется асинхронная обёртка Serilog.Sinks.Async, Serilog.Sinks.Background)
Также
Monitor.TryEnter
позволяет задать таймаут ожидания блокировки.Сигналы
Кроме блокировок, класс
Monitor
можно использовать для передачи сигналов между потоками.Чтобы это сделать, вначале нужно захватить lock на объекте.
Затем, вызвав метод
Monitor.Wait
, можно заблокировать поток и освободить лок.Другой поток может вызвать
Pulse
или PulseAll
— тогда, при выходе из критической секции возобновится выполнение потоков, ждущих с помощью Wait
. PulseAll
сигнализирует все потоки, а Pulse
— один (при этом, Pulse
можно вызвать несколько раз чтобы сигнализировать нужное число потоков).Пример с двумя потоками:
var obj = new object();
var t1 = new Thread(() =>
{
lock (obj)
{
Console.WriteLine("entered lock on thread 1");
Monitor.Wait(obj);
Console.WriteLine("got signal on thread 1");
}
});
var t2 = new Thread(() =>
{
Thread.Sleep(1000);
lock (obj)
{
Console.WriteLine("entered lock on thread 2");
Monitor.Pulse(obj);
Console.WriteLine("exiting lock on thread 2"); // ещё не разбудили первый поток, это случится лишь по выходу из лока.
}
});
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Результат:
entered lock on thread 1
entered lock on thread 2
exiting lock on thread 2
got signal on thread 1
Пример с N потоками и M сигналами остаётся на самостоятельное изучение
Такой способ передачи сигналов я использовал в библиотеке Serilog.Sinks.Background для того, чтобы сигнализировать background-поток о появлении новых лог-сообщений. Но, с дополнительными доработками:
- логирующие потоки не ждут на локе друг друга — они выбирают, какой пойдёт сигнализировать через
Interlocked
- один log event не активирует background-поток — нужно, чтобы в очереди набралось некоторое их количество
- на случай, если логов мало — background-поток активируется по таймауту. В итоге при отладке и выводе логов в консоль — они появляются на экране почти мгновенно, в 60 ФПС (дальше зависит от того, как быстро рендерит терминал)
Однако, такой способ очень рискованный — если никакой поток не вызвал
Monitor.Wait
, то сигнал, отправленный через Monitor.Pulse
будет потерян, что может приводить к дедлокам. Избежать этого помогают более высокоуровневые примитивы синхронизации, но об этом будет уже следующий пост.Метрики
Через свойство
Monitor.LockContentionCount
можно узнать, сколько раз за время выполнения программы потоки останавливались на блокировках, реализованных через класс Monitor
. SpinLock, например, в эту статистику не входит, да и вообще не проявляется в метриках, чем уступает обычным локам в плане поддерживаемости.@epeshkblog | Поддержать канал
█░░░░░░░░░░░░ 28 / 300
GitHub
serilog-sinks-rawconsole/src/Serilog.Sinks.RawConsole/Sinks/RawStreamSink.cs at master · epeshk/serilog-sinks-rawconsole
Write logs to console efficienly. Contribute to epeshk/serilog-sinks-rawconsole development by creating an account on GitHub.
https://learn.microsoft.com/ru-ru/aspnet/signalr/
SignalR - это библиотека для реализации в реальном времени веб-приложений. Она поддерживает несколько методов связи между сервером и клиентом, включая веб-сокеты, Server-Sent Events и long polling.
SignalR - это библиотека для реализации в реальном времени веб-приложений. Она поддерживает несколько методов связи между сервером и клиентом, включая веб-сокеты, Server-Sent Events и long polling.
Docs
SignalR
Microsoft ASP.NET SignalR — это библиотека для разработчиков ASP.NET, которая упрощает процесс добавления веб-функций в режиме реального времени в приложения.
Forwarded from George Drak
Всем привет. Может быть кому-то ещё пригодится. Иногда дебаггер в Rider не может показать значения некоторых переменных, особенно если проваливаться во внешние библиотеки. Выглядит это как ошибка Evaluation is not allowed: The thread is not at a GC-safe point. Оказывается, дебаггеру можно немного помочь, поотключав у приложения различные JIT-оптимизации при помощи переменных окружения.
Это можно сделать прямо в конфиге запуска. После добавления этих настроек у меня стало показывать все значения во внутрянке типа Microsoft.Extensions.DependencyInjection.
SET COMPLUS_ZapDisable=1 NGen off (CLR)
SET COMPLUS_JitMinOpts=1 Disable as much JIT optimizations as possible (CoreCLR)
SET COMPlus_TieredCompilation=0 No tiered JIT, only do one pass (CoreCLR)
SET COMPLUS_ReadyToRun=0 Don't do netcore's analog to NGen (CoreCLR)
Это можно сделать прямо в конфиге запуска. После добавления этих настроек у меня стало показывать все значения во внутрянке типа Microsoft.Extensions.DependencyInjection.
Плюсы работы с SignalR:
1. Реальное время обновлений: SignalR обеспечивает мгновенную доставку обновлений от сервера к клиентам, что позволяет реализовать реальное время в веб-приложениях.
2. Эффективное использование ресурсов: Поскольку SignalR использует механизмы долгосрочных соединений, такие как веб-сокеты или long polling, он может быть более эффективным по сравнению с традиционными методами опроса сервера на предмет обновлений.
3. Простота использования: SignalR предоставляет простой API для отправки и приёма сообщений между сервером и клиентом, что делает его легким для внедрения и использования в проектах.
4. Снижение нагрузки на сервер: Поскольку SignalR позволяет отправлять обновления только при необходимости, он может снизить нагрузку на сервер по сравнению с постоянным опросом клиентов на предмет изменений.
1. Реальное время обновлений: SignalR обеспечивает мгновенную доставку обновлений от сервера к клиентам, что позволяет реализовать реальное время в веб-приложениях.
2. Эффективное использование ресурсов: Поскольку SignalR использует механизмы долгосрочных соединений, такие как веб-сокеты или long polling, он может быть более эффективным по сравнению с традиционными методами опроса сервера на предмет обновлений.
3. Простота использования: SignalR предоставляет простой API для отправки и приёма сообщений между сервером и клиентом, что делает его легким для внедрения и использования в проектах.
4. Снижение нагрузки на сервер: Поскольку SignalR позволяет отправлять обновления только при необходимости, он может снизить нагрузку на сервер по сравнению с постоянным опросом клиентов на предмет изменений.
Минусы:
1. Сложности масштабирования: Хотя SignalR обеспечивает эффективную связь между сервером и клиентами, масштабирование может быть сложным, особенно если требуется обслуживать большое количество одновременных соединений.
2. Необходимость поддержки веб-сокетов: Для использования веб-сокетов, на которых основан SignalR для реального времени обновлений, требуется поддержка со стороны сервера и клиента. Некоторые среды могут иметь ограничения в этом отношении.
3. Сложности отладки: Использование асинхронной связи между сервером и клиентом может сделать отладку сложной, особенно при поиске проблем связанных с сетевым взаимодействием.
Несмотря на эти минусы, в большинстве случаев преимущества использования SignalR для обновления клиентских таблиц через веб-сокеты или long polling перевешивают его недостатки, особенно в задачах, где требуется обеспечить мгновенную доставку данных и реальное время в веб-приложениях.
1. Сложности масштабирования: Хотя SignalR обеспечивает эффективную связь между сервером и клиентами, масштабирование может быть сложным, особенно если требуется обслуживать большое количество одновременных соединений.
2. Необходимость поддержки веб-сокетов: Для использования веб-сокетов, на которых основан SignalR для реального времени обновлений, требуется поддержка со стороны сервера и клиента. Некоторые среды могут иметь ограничения в этом отношении.
3. Сложности отладки: Использование асинхронной связи между сервером и клиентом может сделать отладку сложной, особенно при поиске проблем связанных с сетевым взаимодействием.
Несмотря на эти минусы, в большинстве случаев преимущества использования SignalR для обновления клиентских таблиц через веб-сокеты или long polling перевешивают его недостатки, особенно в задачах, где требуется обеспечить мгновенную доставку данных и реальное время в веб-приложениях.
Forwarded from .NET epeshk blog
.NET #opensource: Jint
Периодически буду рассказывать о различных Open Source проектах написанных на .NET (и не только)
Jint 3.8k ⭐️ — JavaScript интерпретатор, целиком написанный на C#. Поддерживает большое подмножество современного JS, позволяет вызывать как JS-код из дотнета, так и в обратную сторону: из JS вызывать .NET-код. Всё работает в одном процессе: не нужно мучаться с деплоем отдельного тяжеловесного движка.
Кроме очевидного переиспользования JS-кода, средствами Jint можно например реализовать в программе расширяемость — дать возможность пользователям писать свои выражения, функции, плагины на JavaScript или другом языке, который можно в него преобразовать. Например, так можно сделать бэкенд для no-code платформы, где пользователь работает с визуальным языком.
Также могут пригодиться:
- JavaScript Engine Switcher — единый фронтенд для вызова JS-кода из .NET с возможностью заменить движок
- Jurassic и NiL.JS — альтернативы Jint
- NFun, NCalc — интерпретаторы выражений. Полезны, если надо поддержать выполнение простых пользовательских выражений, а JavaScript — дополнительная сложность (не забываем про задачи-загадки вида
@epeshkblog | Поддержать канал
Периодически буду рассказывать о различных Open Source проектах написанных на .NET (и не только)
Jint 3.8k ⭐️ — JavaScript интерпретатор, целиком написанный на C#. Поддерживает большое подмножество современного JS, позволяет вызывать как JS-код из дотнета, так и в обратную сторону: из JS вызывать .NET-код. Всё работает в одном процессе: не нужно мучаться с деплоем отдельного тяжеловесного движка.
Кроме очевидного переиспользования JS-кода, средствами Jint можно например реализовать в программе расширяемость — дать возможность пользователям писать свои выражения, функции, плагины на JavaScript или другом языке, который можно в него преобразовать. Например, так можно сделать бэкенд для no-code платформы, где пользователь работает с визуальным языком.
Также могут пригодиться:
- JavaScript Engine Switcher — единый фронтенд для вызова JS-кода из .NET с возможностью заменить движок
- Jurassic и NiL.JS — альтернативы Jint
- NFun, NCalc — интерпретаторы выражений. Полезны, если надо поддержать выполнение простых пользовательских выражений, а JavaScript — дополнительная сложность (не забываем про задачи-загадки вида
{}+[] == []+{}
)@epeshkblog | Поддержать канал
GitHub
GitHub - sebastienros/jint: Javascript Interpreter for .NET
Javascript Interpreter for .NET. Contribute to sebastienros/jint development by creating an account on GitHub.