Библиотека шарписта | C#, F#, .NET, ASP.NET
Все самое полезное для C#-разработчика в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/b60af5a4 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
إظهار المزيد📈 نظرة تحليلية على قناة تيليجرام Библиотека шарписта | C#, F#, .NET, ASP.NET
تُعد قناة Библиотека шарписта | C#, F#, .NET, ASP.NET (@csharpproglib) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 21 865 مشتركاً، محتلاً المرتبة 6 209 في فئة التكنولوجيات والتطبيقات والمرتبة 30 824 في منطقة روسيا.
📊 مؤشرات الجمهور والحراك
منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 21 865 مشتركاً.
بحسب آخر البيانات بتاريخ 11 يونيو, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار -95، وفي آخر 24 ساعة بمقدار -6، مع بقاء الوصول العام مرتفعاً.
- حالة التحقق: غير موثّقة
- معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 12.48%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً 7.13% من ردود الفعل نسبةً إلى إجمالي المشتركين.
- وصول المنشورات: يحصل كل منشور على متوسط 2 729 مشاهدة. وخلال اليوم الأول يجمع عادةً 1 560 مشاهدة.
- التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 9.
- الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل .net, шарписта, навигация, await, string.
📝 الوصف وسياسة المحتوى
يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
“Все самое полезное для C#-разработчика в одном канале.
По рекламе: @proglib_adv
Учиться у нас: https://proglib.io/w/b60af5a4
Для обратной связи: @proglibrary_feeedback_bot
РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead”
بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 12 يونيو, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.
public interface IBackgroundTaskQueue
{
ValueTask QueueAsync(Func<CancellationToken, Task> workItem);
ValueTask<Func<CancellationToken, Task>> DequeueAsync(CancellationToken cancellationToken);
}
public class BackgroundTaskQueue : IBackgroundTaskQueue
{
private readonly Channel<Func<CancellationToken, Task>> _queue;
public BackgroundTaskQueue(int capacity = 100)
{
var options = new BoundedChannelOptions(capacity)
{
SingleReader = false,
SingleWriter = false,
FullMode = BoundedChannelFullMode.Wait
};
_queue = Channel.CreateBounded<Func<CancellationToken, Task>>(options);
}
public async ValueTask QueueAsync(Func<CancellationToken, Task> workItem)
=> await _queue.Writer.WriteAsync(workItem);
public async ValueTask<Func<CancellationToken, Task>> DequeueAsync(CancellationToken cancellationToken)
=> await _queue.Reader.ReadAsync(cancellationToken);
}
Фоновые сервисы для обработки:
public class BackgroundWorker : BackgroundService
{
private readonly IBackgroundTaskQueue _taskQueue;
private readonly ILogger<BackgroundWorker> _logger;
public BackgroundWorker(IBackgroundTaskQueue taskQueue, ILogger<BackgroundWorker> logger)
{
_taskQueue = taskQueue;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Фоновый worker запущен");
while (!stoppingToken.IsCancellationRequested)
{
var workItem = await _taskQueue.DequeueAsync(stoppingToken);
try
{
await workItem(stoppingToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при выполнении задачи");
}
}
_logger.LogInformation("Worker останавливается...");
}
}
Использование в контроллере:
app.MapPost("/send-email", async (IBackgroundTaskQueue queue) =>
{
await queue.QueueAsync(async token =>
{
await Task.Delay(1000, token); // имитация отправки
Console.WriteLine($"Email отправлен в {DateTime.UtcNow}");
});
return Results.Accepted();
});
Запрос возвращается немедленно, а работа продолжается в фоне. Queue автоматически буферизирует задачи, управляет нагрузкой и применяет обратное давление, если очередь переполнится.
Когда использовать этот подход
Подходит:
• Внутренняя обработка задач в приложении
• Нет нужды в UI-панели мониторинга
• Self-contained сервисы
Возьмите библиотеку, если:
• Нужна распределённая обработка
• Требуется веб-интерфейс для управления
• Задачи должны пережить перезагрузку приложения
➡️ Источник
🐸 Библиотека шарписта
#sharp_view[0][1][1][2][3][3][4] ответ будет [1][3].
Для решения можно воспользоваться подсчётом количества появлений каждого числа.
Если встретили число во второй раз — записываем его в ответ:
public int[] GetSneakyNumbers(int[] nums)
{
int n = nums.Length;
int[] count = new int[101];
int[] res = new int[2];
int idx = 0;
foreach (var num in nums)
{
count[num]++;
if (count[num] == 2)
{
res[idx] = num;
idx++;
}
}
return res;
}
При помощи вспомогательного массива считаем, сколько раз встречается каждое число, и когда оно появилось второй раз — запоминаем.
➡️ Попробовать решить
🐸 Библиотека шарписта
#dotnet_challengevar errors = File.ReadLines(logPath).Where(l => l.Contains("ERROR"));
ReadLines читает файл построчно, не загружая всё сразу.
Не добавляйте .ToList(), если хочется сохранить ленивость — иначе всё материализуется в памяти.
🐸 Библиотека шарписта
#sharp_viewpublic async Task<bool> SaveWithRetryAsync(DbContext context, int maxRetries = 3)
{
for (int attempt = 0; attempt < maxRetries; attempt++)
{
try
{
await context.SaveChangesAsync();
return true;
}
catch (DbUpdateException ex) when (IsDeadlock(ex))
{
if (attempt == maxRetries - 1)
throw;
// Экспоненциальная задержка: 100ms, 200ms, 400ms
var delay = TimeSpan.FromMilliseconds(100 * Math.Pow(2, attempt));
await Task.Delay(delay);
Console.WriteLine($"Deadlock detected, retry {attempt + 1}/{maxRetries}");
}
}
return false;
}
bool IsDeadlock(Exception ex) =>
ex.InnerException is SqlException sqlEx &&
(sqlEx.Number == 1205 || // Deadlock victim
ex.InnerException.Message.Contains("deadlocked"));
• Ограничение параллелизма
Если ваше приложение обрабатывает большие пакеты данных, ограничьте количество одновременных операций:
public class OrderProcessor
{
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(5); // Макс 5 одновременно
public async Task ProcessOrdersAsync(List<int> orderIds)
{
var tasks = orderIds.Select(id => ProcessWithSemaphoreAsync(id));
await Task.WhenAll(tasks);
}
private async Task ProcessWithSemaphoreAsync(int orderId)
{
await _semaphore.WaitAsync();
try
{
await using var context = new AppDbContext();
var order = await context.Orders.FindAsync(orderId);
order.Status = "Processed";
await SaveWithRetryAsync(context);
}
finally
{
_semaphore.Release();
}
}
}
• Логирование и анализ
Недостаточно просто повторить — нужно понять причину:
catch (DbUpdateException ex) when (IsDeadlock(ex))
{
_logger.LogWarning(ex,
"Deadlock on order {OrderId}, attempt {Attempt}/{MaxAttempts}",
orderId, attempt + 1, maxRetries);
// Отправьте метрику в мониторинг
_telemetry.TrackMetric("Deadlocks", 1, new Dictionary<string, string>
{
["Entity"] = "Order",
["Operation"] = "Update"
});
}
• Захват графов блокировок
SQL Server создаёт подробные графы взаимоблокировок. Настройте их захват:
-- Extended Events для захвата deadlock
CREATE EVENT SESSION [DeadlockMonitoring] ON SERVER
ADD EVENT sqlserver.xml_deadlock_report
ADD TARGET package0.event_file(SET filename = N'C:\Logs\Deadlocks.xel')
WITH (MAX_MEMORY = 4096 KB, EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS);
ALTER EVENT SESSION [DeadlockMonitoring] ON SERVER STATE = START;
Сочетание правильного предотвращения и надежного восстановления создаст устойчивую систему, способную справиться с любыми нагрузками.
Чтобы строить надёжные решения нужно знать архитектуру и уметь её спроектировать. Для этого можно пройти наш интенсив по архитектуре и шаблонам проектирования. Осталось всего 3 дня скидок!
🐸 Библиотека шарписта
#sharp_viewSqlException: Transaction (Process ID xx) was deadlocked on resources...Пример простого дедлока: два контекста одновременно меняют одну строку и пытаются сохранить изменения. Один запрос блокирует строку, второй вызывает дедлок.
await using var context1 = new AppDbContext();
await using var context2 = new AppDbContext();
var order1 = await context1.Orders.FindAsync(1);
var order2 = await context2.Orders.FindAsync(1);
order1.Status = "Paid";
order2.Status = "Shipped";
await context1.SaveChangesAsync(); // Блокирует строку
await context2.SaveChangesAsync(); // Возможен deadlock
Стратегии предотвращения
• Короткие транзакции
Минимизируйте работу внутри транзакции:
await using var tx = await context.Database.BeginTransactionAsync();
var order = await context.Orders.FindAsync(orderId);
order.Status = "Paid";
await context.SaveChangesAsync();
await tx.CommitAsync();
Избегайте сетевых вызовов и посторонних запросов перед коммитом.
• Правильные индексы
Отсутствие индексов приводит к сканированию таблиц и длительным блокировкам. Используйте SQL Profiler для мониторинга.
• Оптимальный уровень изоляции
ReadCommitted обычно достаточен для большинства операций:
await using var tx = await context.Database.BeginTransactionAsync(
IsolationLevel.ReadCommitted);
• Логика повторов
Используйте встроенную политику retry в EF Core:
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(connectionString, sql =>
sql.EnableRetryOnFailure(
maxRetryCount: 3,
maxRetryDelay: TimeSpan.FromSeconds(5),
errorNumbersToAdd: null)));
• RowVersion для контроля конкурентности
public class Order
{
public int Id { get; set; }
public string Status { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
EF Core выбросит DbUpdateConcurrencyException при конфликте изменений.
Дедлоки не баги, а следствие паттернов конкурентного доступа.
🐸 Библиотека шарписта
#sharp_viewvar last10 = text[^10..];
Такой способ делает код короче и легче для чтения.
Но есть один момент — если строка короче десяти символов, программа выбросит ошибку.
Чтобы этого избежать, добавьте проверку:
var last10 = text.Length >= 10 ? text[^10..] : text;Теперь код работает безопасно даже с короткими строками. 🐸 Библиотека шарписта #sharp_view
متاح الآن! بحث تيليغرام 2025 — أهم رؤى العام 
