C# (C Sharp) programming
По всем вопросам- @notxxx1 Реестр РКН: https://clck.ru/3Fk3kb #VRHSZ
Ko'proq ko'rsatish📈 Telegram kanali C# (C Sharp) programming analitikasi
C# (C Sharp) programming (@csharp_ci) Rus til segmentidagi kanali faol ishtirokchi. Hozirda hamjamiyat 18 308 obunachidan iborat bo'lib, Texnologiyalar & Aralashmalar toifasida 7 330-o'rinni va Rossiya mintaqasida 36 862-o'rinni egallagan.
📊 Auditoriya ko‘rsatkichlari va dinamika
невідомо sanasidan buyon loyiha tez o‘sib, 18 308 obunachiga ega bo‘ldi.
13 Iyun, 2026 dagi oxirgi ma’lumotlarga ko‘ra kanal barqaror faollikka ega. Oxirgi 30 kunda obunachilar soni -3 ga, so‘nggi 24 soatda esa 7 ga o‘zgardi va umumiy qamrov yuqori darajada qolmoqda.
- Tasdiqlash holati: Tasdiqlanmagan
- Jalb etish (ER): Auditoriya o‘rtacha 18.51% darajada jalb etiladi. Nashrdan keyingi dastlabki 24 soatda kontent odatda umumiy obunachilar sonining 7.49% ini tashkil etuvchi reaksiyalarni to‘playdi.
- Post qamrovi: Har bir post o‘rtacha 3 390 marta ko‘riladi; birinchi sutkada odatda 1 371 ta ko‘rish yig‘iladi.
- Reaksiyalar va o‘zaro ta’sir: Auditoriya faol: har bir postga o‘rtacha 0 ta reaksiya keladi.
- Tematik yo‘nalishlar: Kontent .net, api, логика, архитектура, string kabi asosiy mavzularga jamlangan.
📝 Tavsif va kontent siyosati
Muallif resursni shaxsiy fikrni ifoda etish maydoni sifatida ta’riflaydi:
“По всем вопросам- @notxxx1
Реестр РКН: https://clck.ru/3Fk3kb
#VRHSZ”
Yuqori yangilanish chastotasi (oxirgi ma’lumot 14 Iyun, 2026 da olingan) sababli kanal doimo dolzarb va katta qamrovli bo‘lib qoladi. Analitika auditoriya kontent bilan faol hamkorlik qilishini, uni Texnologiyalar & Aralashmalar toifasidagi muhim ta’sir nuqtasiga aylantirishini ko‘rsatadi.
push в Git-репозиторий или интерфейс личного кабинета.
После этого развертывание, установка зависимостей и настройка произойдут автоматически.
📎 Подробнее
@csharp_ciSemaphore.
Для создания семафора применяется один из конструкторов класса Semaphore:
🟡Semaphore (int initialCount, int maximumCount)
параметр initialCount задает начальное количество потоков, а maximumCount — максимальное количество потоков, которые имеют доступ к общим ресурсам: initialCount — изначальное доступное количество свободных мест, maximumCount — вместимость.
🟡Semaphore (int initialCount, int maximumCount, string? name) в дополнение задает имя семафора
🟡Semaphore (int initialCount, int maximumCount, string? name, out bool createdNew): последний параметр — createdNew при значении true указывает, что новый семафор был успешно создан. Если этот параметр равен false, то семафор с указанным именем уже существует
Для работы с потоками класс Semaphore имеет 2 основных метода:
— WaitOne() ожидает получения свободного места в семафоре
— Release() освобождает место в семафоре
В отличие от lock (Monitor) и Mutex, у Semaphore нет «владельца» — он не зависит от потока. Любой поток может вызвать Release на семафоре, тогда как с Mutex и блокировкой только поток, получивший блокировку, может ее освободить.
// запускаем пять потоков
for (int i = 1; i < 6; i++)
{
Reader reader = new Reader(i);
}
class Reader
{
// создаем семафор
static Semaphore sem = new Semaphore(3, 3);
Thread myThread;
int count = 3;// счетчик чтения
public Reader(int i)
{
myThread = new Thread(Read);
myThread.Name = $"Читатель {i}";
myThread.Start();
}
public void Read()
{
while (count > 0)
{
sem.WaitOne(); // ожидаем, когда освободиться место
Console.WriteLine($"{Thread.CurrentThread.Name} входит в библиотеку");
Console.WriteLine($"{Thread.CurrentThread.Name} читает");
Thread.Sleep(1000);
Console.WriteLine($"{Thread.CurrentThread.Name} покидает библиотеку");
sem.Release(); // освобождаем место
count--;
Thread.Sleep(1000);
}
}
}
@csharp_ciint[] simpleArray = {0, 1, 2, 3, 4, 5, 6, 7, 8};
ref int simpleElementRef = ref simpleArray[3];
В этом примере simpleElementRef — ссылка на simpleArray[3]. Изменение simpleElementRef приводит к изменению элемента массива:
simpleElementRef *= 15; Console.WriteLine(simpleElementRef); // 15 Console.WriteLine(simpleArray[3]); // 15🟡В качестве цели ссылочной локальной переменной может быть указан элемент массива, поле, или обычная локальная переменная. Целью не может быть свойство. Ссылочные локальные переменные используются для специальных сценариев микро-оптимизации и как правило применяются в сочетании с возвращаемыми ссылочными значениями. 🟡Также ссылочные локальные переменные можно возвращать из методов. В результате получаем возвращаемое ссылочное значение:
static string X = "Старое значение";
static ref string GetX() => ref X; // Возвращает ссылочное значение
static void Main()
{
ref string xRef = ref GetX(); // Присваивает результат ссылочной локальной переменной
xRef = "Новое значение";
Console.WriteLine(X); // Выводит Новое значение
}
📎 Подробнее
@csharp_ciTask.Yield() возвращает специальное значение, предназначенное для передачи оператору await, и в отрыве от этого оператора не имеющее смысла.
Конструкция же await Task.Yield() делает довольно простую вещь — прерывает текущий метод и сразу же планирует его продолжение в текущем контексте синхронизации.
Используется же эта конструкция для разных целей.
🟡Во-первых, эта конструкция может быть использована для немедленного возврата управления вызывающему коду. Например, при вызове из обработчика события событие будет считаться обработанным:
protected override async void OnClosing(CancelEventArgs e)
{
e.Cancel = true;
await Task.Yield();
// (какая-то логика)
}
🟡Во-вторых, эта конструкция используется для очистки синхронного контекста вызова. Например, так можно "закрыть" текущую транзакцию (ambient transaction):
using (var ts = new TransactionScope()) {
// ...
Foo();
// ...
ts.Complete();
}
async void Foo() {
// ... тут мы находимся в контексте транзакции
if (Transaction.Current != null) await Task.Yield();
// ... а тут его уже нет!
}
🟡В-третьих, эта конструкция может очистить стек вызовов. Это может быть полезным, если программа падает с переполнением стека при обработке кучи вложенных продолжений.
Например, рассмотрим упрощенную реализацию AsyncLock:
class AsyncLock
{
private Task unlockedTask = Task.CompletedTask;
public async Task<Action> Lock()
{
var tcs = new TaskCompletionSource<object>();
await Interlocked.Exchange(ref unlockedTask, tcs.Task);
return () => tcs.SetResult(null);
}
}
Здесь поступающие запросы на получение блокировки выстраиваются в неявную очередь на продолжениях. Казалось бы, что может пойти не так?
private static async Task Foo()
{
var _lock = new AsyncLock();
var unlock = await _lock.Lock();
for (var i = 0; i < 100000; i++) Bar(_lock);
unlock();
}
private static async void Bar(AsyncLock _lock)
{
var unlock = await _lock.Lock();
// do something sync
unlock();
}
Здесь продолжение метода Bar вызывается в тот момент, когда другой метод Bar выполняет вызов unlock(). Получается косвенная рекурсия между методом Bar и делегатом unlock, которая быстро сжирает стек и ведет к его переполнению.
Добавление же вызова Task.Yield() перенесет исполнение в "чистый" фрейм стека, и ошибка исчезнет:
class AsyncLock
{
private Task unlockedTask = Task.CompletedTask;
public async Task<Action> Lock()
{
var tcs = new TaskCompletionSource<object>();
var prevTask = Interlocked.Exchange(ref unlockedTask, tcs.Task);
if (!prevTask.IsCompleted)
{
await prevTask;
await Task.Yield();
}
return () => tcs.SetResult(null);
}
}
@csharp_ci├╼ Устанавливаем .NET на Ubuntu 22.04
├╼ Создаём проект
├╼ Запускаем сборку в GitHub Actions
├╼ Используем секреты в коде тестов
╰╼ Размещаем секреты в GitHub Actions Secrets
📎 Туториал
🖥 GitHub
@csharp_ciFile:
[HttpGet("file/{guid}/download")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<IActionResult> DownloadFile([FromRoute] Guid guid)
{
var file = await _mediaContentService.DownloadFile(guid);
return File(file.Stream, file.ContentType, file.FileName);
}
Можно ли каким-либо образом реализовать ограничение на скачивание файла, чтобы, например, в единицу времени не больше N пользователей качало файл?
▶️Проблема с методом File — он возвращает ленивый ответ. Т.е. он не читает весь поток сразу, а ждет пока будет вызван метод от IActionResult.
Чтобы эту проблему решить, надо знать, когда файл точно отправлен.
Можно сделать специальный декоратор. Например:
[ApiController]
[Route("[controller]")]
public class SampleController : ControllerBase
{
private readonly IRateLimiter _rateLimiter;
public SampleController(IRateLimiter rateLimiter)
{
_rateLimiter = rateLimiter;
}
[HttpGet("connection")]
public async Task<IActionResult> DownLoadFile(Guid file)
{
var stream = await GetFileStream(file);
return new RateLimiterFileActionResult(File(stream, "content/type", "sample.txt"), _rateLimiter);
}
}
class RateLimiterFileActionResult : IActionResult
{
private readonly IActionResult _actionResultImplementation;
private readonly IRateLimiter _rateLimiter;
public RateLimiterFileActionResult(IActionResult actionResultImplementation, IRateLimiter rateLimiter)
{
_actionResultImplementation = actionResultImplementation;
_rateLimiter = rateLimiter;
}
public async Task ExecuteResultAsync(ActionContext context)
{
try
{
await _rateLimiter.ObtainAsync(context.HttpContext.RequestAborted);
await _actionResultImplementation.ExecuteResultAsync(context);
}
finally
{
await _rateLimiter.ReleaseAsync(context.HttpContext.RequestAborted);
}
}
}
public interface IRateLimiter
{
public Task ObtainAsync(CancellationToken token);
public Task ReleaseAsync(CancellationToken token);
}
Стоит заметить, что блокировка берётся внутри метода декоратора, а не в методе контроллера.
@csharp_ci
Endi mavjud! Telegram Tadqiqoti 2025 — yilning asosiy insaytlari 
