This media is not supported in your browser
VIEW IN TELEGRAM
Так сказал мой друг из Африки, когда увидел этот стол)
Не знаю уж че за сетап, меня зовут Саша и качественную необычную мебель из натурального дерева я делаю уже больше 12-ти лет, столько же занимаюсь и темой здоровья.
Когда я услышал, что до 10% смертности связано с сидячим образом жизни, меня это поразило и я задался целью делать максимально функциональные и полезные рабочие пространства, ибо геморрой в 30 это конечно довольно нишево, но все же сомнительно 😂
Ну а собрать такой комплект под свои задачи и при этом сразу прикинуть цены вы можете в удобном Mini App конструкторе
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2❤1🔥1
Отправляем несколько HTTP-запросов параллельно на C#!
Если данные нужно получить из нескольких независимых источников, последовательные запросы заставят программу ждать каждый ответ по очереди.
Создадим HttpClient:
Запустим три запроса без немедленного ожидания результата:
Теперь все операции уже выполняются параллельно. Дождёмся завершения всей группы:
Получим готовые результаты:
Если каждый запрос занимает около секунды, последовательное выполнение продлится примерно три секунды, а параллельное около одной.
Добавим ограничение общего времени ожидания:
Передадим токен отмены запросу:
Так приложение сможет прекратить операцию, если внешний сервис отвечает слишком долго.
➡️ C# Ready | #практика
Если данные нужно получить из нескольких независимых источников, последовательные запросы заставят программу ждать каждый ответ по очереди.
Создадим HttpClient:
using var client = new HttpClient
{
Timeout = TimeSpan.FromSeconds(10)
};
Запустим три запроса без немедленного ожидания результата:
Task<string> usersTask =
client.GetStringAsync(usersUrl);
Task<string> ordersTask =
client.GetStringAsync(ordersUrl);
Task<string> ratesTask =
client.GetStringAsync(ratesUrl);
Теперь все операции уже выполняются параллельно. Дождёмся завершения всей группы:
await Task.WhenAll(
usersTask,
ordersTask,
ratesTask
);
Получим готовые результаты:
string users = await usersTask;
string orders = await ordersTask;
string rates = await ratesTask;
Если каждый запрос занимает около секунды, последовательное выполнение продлится примерно три секунды, а параллельное около одной.
Добавим ограничение общего времени ожидания:
using var cts =
new CancellationTokenSource(
TimeSpan.FromSeconds(5)
);
Передадим токен отмены запросу:
string data = await client.GetStringAsync(
usersUrl,
cts.Token
);
Так приложение сможет прекратить операцию, если внешний сервис отвечает слишком долго.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥5❤2
Шпаргалка по форматированию даты и времени в C#!
Например, dd.MM.yyyy выведет дату с числом, месяцем и годом, HH:mm покажет время в 24-часовом формате, а MMM и MMMM позволяют получить сокращённое или полное название месяца.
На картинке спецификаторы для дня, месяца, года, часов, минут, секунд, долей секунды, часового пояса и AM/PM. Для каждого варианта приведены готовый формат и пример результата.
Сохрани, чтобы не потерять!
➡️ C# Ready | #ресурс
Например, dd.MM.yyyy выведет дату с числом, месяцем и годом, HH:mm покажет время в 24-часовом формате, а MMM и MMMM позволяют получить сокращённое или полное название месяца.
На картинке спецификаторы для дня, месяца, года, часов, минут, секунд, долей секунды, часового пояса и AM/PM. Для каждого варианта приведены готовый формат и пример результата.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥7❤3
Почему with у record не создаёт глубокую копию?
Выражение with удобно использовать для создания изменённой копии record:
Но копирование будет поверхностным. Сам record создаётся заново, а вложенные ссылочные объекты продолжают использоваться совместно.
Рассмотрим record со списком:
Создадим его копию и изменим список:
Изменение появится и в исходном объекте:
Причина в том, что original.Roles и copy.Roles ссылаются на один экземпляр List<string>.
Если списки должны быть независимыми, скопируйте коллекцию явно:
Другой вариант использовать неизменяемые коллекции:
Это касается не только списков, но также массивов, словарей и других изменяемых ссылочных объектов.
➡️ C# Ready | #совет
Выражение with удобно использовать для создания изменённой копии record:
var updated = user with
{
Name = "Alex"
};
Но копирование будет поверхностным. Сам record создаётся заново, а вложенные ссылочные объекты продолжают использоваться совместно.
Рассмотрим record со списком:
record User(
string Name,
List<string> Roles
);
Создадим его копию и изменим список:
var original = new User(
"Alex",
new() { "read" }
);
var copy = original with { };
copy.Roles.Add("write");
Изменение появится и в исходном объекте:
Console.WriteLine(
original.Roles.Count
);
// 2
Причина в том, что original.Roles и copy.Roles ссылаются на один экземпляр List<string>.
Если списки должны быть независимыми, скопируйте коллекцию явно:
var copy = original with
{
Roles = new List<string>(
original.Roles
)
};
Другой вариант использовать неизменяемые коллекции:
record User(
ImmutableArray<string> Roles
);
var copy = original with
{
Roles = original.Roles.Add("write")
};
Это касается не только списков, но также массивов, словарей и других изменяемых ссылочных объектов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥5❤3
Интересный разбор того, как сегодня создавать игры на C# без готового движка!
В этой статье:
• Почему C# подходит для небольших кроссплатформенных игр
• Как SDL3 закрывает окна, ввод, контроллеры и рендеринг
• Как организовать загрузку ассетов и собрать собственный редактор на Dear ImGui
➡️ C# Ready | #статья
В этой статье:
• Почему C# подходит для небольших кроссплатформенных игр
• Как SDL3 закрывает окна, ввод, контроллеры и рендеринг
• Как организовать загрузку ассетов и собрать собственный редактор на Dear ImGui
Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4🔥4
IT мероприятия 🤘
Всё самое интересное для карьеры в IT: митапы, хакатоны, конференции, стажировки и обучение.
Подписывайся🤘
1. Москва
2. Санкт-Петербург
3. Для стажеров и студентов
Всё самое интересное для карьеры в IT: митапы, хакатоны, конференции, стажировки и обучение.
Подписывайся
1. Москва
2. Санкт-Петербург
3. Для стажеров и студентов
Please open Telegram to view this post
VIEW IN TELEGRAM
CancellationToken должен проходить через всю цепочку вызовов!
Само наличие
Если вложенные методы не получили токен, они продолжат работать даже после отмены запроса.
Токен нужно передавать во все операции, которые поддерживают отмену:
Для вычислений без
Отмена в .NET кооперативная:
Для собственного таймаута можно создать источник отмены:
Если одновременно нужен токен вызывающего кода и внутренний таймаут, их можно объединить:
Передавайте
➡️ C# Ready | #совет
Само наличие
CancellationToken в параметрах ещё не делает операцию отменяемой:async Task SyncAsync(CancellationToken token)
{
var data = await LoadAsync();
await SaveAsync(data);
}
Если вложенные методы не получили токен, они продолжат работать даже после отмены запроса.
Токен нужно передавать во все операции, которые поддерживают отмену:
var data = await LoadAsync(token);
await SaveAsync(data, token);
await Task.Delay(500, token);
Для вычислений без
await запрос отмены необходимо проверять вручную:foreach (var item in items)
{
token.ThrowIfCancellationRequested();
Process(item);
}
Отмена в .NET кооперативная:
Cancel() не останавливает код принудительно. Он только сообщает операциям, что работу следует завершить.Для собственного таймаута можно создать источник отмены:
using var timeout = new CancellationTokenSource(
TimeSpan.FromSeconds(10)
);
await SyncAsync(timeout.Token);
Если одновременно нужен токен вызывающего кода и внутренний таймаут, их можно объединить:
using var linked = CancellationTokenSource
.CreateLinkedTokenSource(token, timeout.Token);
await SyncAsync(linked.Token);
Передавайте
CancellationToken до самого нижнего отменяемого вызова, иначе API обещает отмену, но фактическая работа продолжается.Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍4🔥3
«Снова в школу!» – звучит тревожно.
Но в магистратуре МИФИ и Школы 21 «Управление внедрением искусственного интеллекта в бизнес» совсем другая атмосфера: тут нет страха ошибки и ощущения, что зря тратишь время.
Зато есть рабочая среда, поддержка единомышленников и уверенность, что растёшь.
Что внутри программы:
— не просто алгоритмы, а живые сценарии – где применить ИИ, чтобы было лучше, быстрее, дешевле;
— учим внедрять ИИ для управления продуктом от технического задания до запуска;
— делаешь реальные проекты прямо во время учёбы, а не ближе к диплому;
— диплом государственного образца МИФИ – одного из ведущих технических университетов страны.
Подробности и заявка здесь
Но в магистратуре МИФИ и Школы 21 «Управление внедрением искусственного интеллекта в бизнес» совсем другая атмосфера: тут нет страха ошибки и ощущения, что зря тратишь время.
Зато есть рабочая среда, поддержка единомышленников и уверенность, что растёшь.
Что внутри программы:
— не просто алгоритмы, а живые сценарии – где применить ИИ, чтобы было лучше, быстрее, дешевле;
— учим внедрять ИИ для управления продуктом от технического задания до запуска;
— делаешь реальные проекты прямо во время учёбы, а не ближе к диплому;
— диплом государственного образца МИФИ – одного из ведущих технических университетов страны.
Подробности и заявка здесь
👎1🔥1😁1
Это потокобезопасная очередь для передачи сообщений между задачами без ручных блокировок и сложной синхронизации.
Что важно знать:
• Работает без ручных блокировок и сложных синхронных вызовов.
• Позволяет автоматически замедлять отправку при перегрузке памяти.
• Обеспечивает плавную передачу данных между параллельными задачами.
Так вы получаете готовый «из коробки» механизм асинхронной очереди с естественным управлением нагрузкой без лишнего кода.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤5👍3🤝1
Понятный разбор того, как на самом деле работает async/await в C#!
В этой статье:
• Чем асинхронность отличается от запуска работы в отдельном потоке
• Когда await освобождает поток, а когда выполнение продолжается синхронно
• Как компилятор превращает асинхронный метод в машину состояний
➡️ C# Ready | #статья
В этой статье:
• Чем асинхронность отличается от запуска работы в отдельном потоке
• Когда await освобождает поток, а когда выполнение продолжается синхронно
• Как компилятор превращает асинхронный метод в машину состояний
Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4🔥3
Почему yield return в C# выполняется не сразу?
Метод с yield выглядит как обычный метод:
Но при вызове код внутри ещё не выполняется:
В консоли сначала будет:
А строка start появится только тогда, когда коллекцию начнут реально перебирать:
И вот тогда выполнение пойдёт пошагово:
Это важно помнить, если внутри iterator-метода есть чтение файла, запрос к базе, логирование или любая другая побочная логика.
Например, такой код может выполнить запрос не там, где кажется:
LoadUsers() может начать работу только на foreach, а не на первой строке.
Если нужно зафиксировать результат сразу, материализуй последовательность:
yield return создаёт ленивую последовательность. Код внутри запускается при перечислении, а не при вызове метода.
➡️ C# Ready | #совет
Метод с yield выглядит как обычный метод:
IEnumerable<int> GetNumbers()
{
Console.WriteLine("start");
yield return 1;
yield return 2;
}
Но при вызове код внутри ещё не выполняется:
var numbers = GetNumbers();
Console.WriteLine("created");
В консоли сначала будет:
created
А строка start появится только тогда, когда коллекцию начнут реально перебирать:
foreach (var number in numbers)
{
Console.WriteLine(number);
}
И вот тогда выполнение пойдёт пошагово:
start
1
2
Это важно помнить, если внутри iterator-метода есть чтение файла, запрос к базе, логирование или любая другая побочная логика.
Например, такой код может выполнить запрос не там, где кажется:
var users = LoadUsers();
DoSomething();
foreach (var user in users)
{
Console.WriteLine(user.Name);
}
LoadUsers() может начать работу только на foreach, а не на первой строке.
Если нужно зафиксировать результат сразу, материализуй последовательность:
var users = LoadUsers().ToList();
yield return создаёт ленивую последовательность. Код внутри запускается при перечислении, а не при вызове метода.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍3🔥2
Простая и популярная статья о создании Telegram-бота на C#!
В этой статье:
• Как создать бота через BotFather и подключить его к проекту
• Как принимать сообщения пользователя и отправлять ответы
• Как собрать базу, от которой уже можно развивать своего бота дальше
➡️ C# Ready | #статья
В этой статье:
• Как создать бота через BotFather и подключить его к проекту
• Как принимать сообщения пользователя и отправлять ответы
• Как собрать базу, от которой уже можно развивать своего бота дальше
Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍4🔥3
Шпаргалка по недооценённым LINQ-методам в C#!
Например, SequenceEqual() помогает сравнить две последовательности по элементам, ToLookup() создаёт удобную группировку для быстрого доступа по ключу, а GroupJoin() полезен, когда нужно связать две коллекции и получить вложенный результат.
На картинке 5 LINQ-методов с короткими примерами кода: SequenceEqual, Aggregate, GroupJoin, ToLookup и Intersect.
Сохрани, чтобы не потерять!
➡️ C# Ready | #ресурс
Например, SequenceEqual() помогает сравнить две последовательности по элементам, ToLookup() создаёт удобную группировку для быстрого доступа по ключу, а GroupJoin() полезен, когда нужно связать две коллекции и получить вложенный результат.
На картинке 5 LINQ-методов с короткими примерами кода: SequenceEqual, Aggregate, GroupJoin, ToLookup и Intersect.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9👍7🔥6
Опа, тут бывший сеньор одного из IT-отделов Яндекса Игорь Никитин выкатил целый канал про Python — и это лучшее, что есть в рунете по теме.
Качественные гайды. Советы от известных прогеров. Тематические мемасы. Короче, ничего лишнего.
Хватит душить питона, учись его кодить: https://t.me/+IzIPzvoa7p40ZTUy 🐍
Качественные гайды. Советы от известных прогеров. Тематические мемасы. Короче, ничего лишнего.
Хватит душить питона, учись его кодить: https://t.me/+IzIPzvoa7p40ZTUy 🐍
👎9
Собираем простую очередь фоновых задач!
Иногда в приложении нужно отложить работу: отправить email, записать аудит, обработать файл или выполнить тяжёлую операцию после ответа пользователю.
Для этого можно собрать небольшую очередь на Channel<T>.
Сначала заведём интерфейс:
Реализация будет хранить задачи внутри Channel:
Добавление задачи:
Чтение задач:
Теперь можно положить работу в очередь:
А отдельный воркер будет выполнять задачи:
В ASP.NET Core такую логику обычно выносят в BackgroundService:
Такой подход помогает не держать HTTP-запрос открытым, если работу можно выполнить после ответа пользователю.
➡️ C# Ready | #практика
Иногда в приложении нужно отложить работу: отправить email, записать аудит, обработать файл или выполнить тяжёлую операцию после ответа пользователю.
Для этого можно собрать небольшую очередь на Channel<T>.
Сначала заведём интерфейс:
public interface ITaskQueue
{
ValueTask EnqueueAsync(Func<CancellationToken, Task> job);
IAsyncEnumerable<Func<CancellationToken, Task>> ReadAllAsync(
CancellationToken token
);
}
Реализация будет хранить задачи внутри Channel:
using System.Threading.Channels;
public sealed class TaskQueue : ITaskQueue
{
private readonly Channel<Func<CancellationToken, Task>> _channel =
Channel.CreateUnbounded<Func<CancellationToken, Task>>();
Добавление задачи:
public ValueTask EnqueueAsync(Func<CancellationToken, Task> job)
{
return _channel.Writer.WriteAsync(job);
}
Чтение задач:
public IAsyncEnumerable<Func<CancellationToken, Task>> ReadAllAsync(
CancellationToken token
)
{
return _channel.Reader.ReadAllAsync(token);
}
}
Теперь можно положить работу в очередь:
await queue.EnqueueAsync(async token =>
{
await emailSender.SendAsync(user.Email, token);
});
А отдельный воркер будет выполнять задачи:
await foreach (var job in queue.ReadAllAsync(token))
{
await job(token);
}
В ASP.NET Core такую логику обычно выносят в BackgroundService:
protected override async Task ExecuteAsync(CancellationToken token)
{
await foreach (var job in queue.ReadAllAsync(token))
{
await job(token);
}
}
Такой подход помогает не держать HTTP-запрос открытым, если работу можно выполнить после ответа пользователю.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍3🔥3