Библиотека шарписта | C#, F#, .NET, ASP.NET
Все самое полезное для C#-разработчика в одном канале. Наши курсы: https://clc.to/y3LDtw По рекламе: @proglib_adv Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
显示更多📈 Telegram 频道 Библиотека шарписта | C#, F#, .NET, ASP.NET 的分析概览
频道 Библиотека шарписта | C#, F#, .NET, ASP.NET (@csharpproglib) 俄语 语言赛道中的 是活跃参与者。目前社区聚集了 21 701 名订阅者,在 技术与应用 类别中位列第 5 943,并在 俄罗斯 地区排名第 30 267 位。
📊 受众指标与增长动态
自 невідомо 创建以来,项目保持高速增长,吸引了 21 701 名订阅者。
根据 29 八月, 2026 的最新数据,频道保持稳定运转。过去 30 天订阅人数变化为 -48,过去 24 小时变化为 -6,整体触达仍然可观。
- 认证状态: 未认证
- 互动率 (ER): 平均受众互动率为 16.72%。内容发布后 24 小时内通常能获得 7.84% 的反应,占订阅者总量。
- 帖子覆盖: 每篇帖子平均可获得 3 628 次浏览,首日通常累积 1 702 次浏览。
- 互动与反馈: 受众积极参与,单帖平均反应数为 23。
- 主题关注点: 内容集中在 .net, шарписта, навигация, await, string 等核心主题上。
📝 描述与内容策略
作者将该频道定位为表达主观观点的平台:
“Все самое полезное для C#-разработчика в одном канале.
Наши курсы: https://clc.to/y3LDtw
По рекламе: @proglib_adv
Для обратной связи: @proglibrary_feeedback_bot
РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead”
凭借高频更新(最新数据采集于 30 八月, 2026),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。
[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
List<T> — это универсальный солдат C#. Но универсальный не значит оптимальный. Пока вы перебираете 10 000 элементов через .FirstOrDefault(), Dictionary находит нужное за одно обращение. И это только начало.
Queue — когда порядок имеет значение
Обрабатываете задачи по очереди? Вот вам готовое решение:
var tasks = new Queue<UserRequest>();
tasks.Enqueue(new UserRequest { Id = 1, Name = "Alice" });
tasks.Enqueue(new UserRequest { Id = 2, Name = "Bob" });
// Безопасное извлечение (с .NET 6+)
while (tasks.TryDequeue(out var request))
{
await ProcessAsync(request);
}
Первым пришел — первым обработался. Никаких индексов, никаких сортировок.
Stack — для истории действий
Делаете undo/redo или навигацию? Стек решает это из коробки:
var history = new Stack<string>();
history.Push("/home");
history.Push("/products");
history.Push("/cart");
// Вернуться назад
if (history.TryPop(out var lastPage))
{
Console.WriteLine($"Back to: {lastPage}"); // /cart
}
Последнее действие всегда доступно первым. Логика браузерной кнопки «Hазад» готова.
Dictionary — когда нужна скорость
Поиск по ключу за O(1) вместо перебора всего списка:
var users = new Dictionary<int, User>();
users.Add(1, new User { Name = "Alice" });
users.Add(2, new User { Name = "Bob" });
// Безопасная проверка
if (users.TryGetValue(2, out var user))
{
Console.WriteLine(user.Name); // Bob
}
Никаких .FirstOrDefault(x => x.Id == 2) с перебором тысяч записей.
List отлично работает, когда вам нужен доступ по индексу и порядок элементов. Но если задача укладывается в одну из этих трёх структур — используйте их.
🐸 Библиотека шарписта
#il_люминатор