Telegram Group & Telegram Channel
πŸ“Œ Π—Π°Π΄Π°Ρ‡Π°: "ВысоконагруТённый кэш с автоматичСской очисткой ΠΈ ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½Ρ‹ΠΌ доступом"

❗️УсловиС:

Π Π΅Π°Π»ΠΈΠ·ΡƒΠΉΡ‚Π΅ класс SmartCache<TKey, TValue> Π² .NET, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π΄ΠΎΠ»ΠΆΠ΅Π½:

- ΠŸΠΎΠ·Π²ΠΎΠ»ΡΡ‚ΡŒ бСзопасно Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ элСмСнты ΠΈΠ· кэша Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС (`Get`, `Set`).
- АвтоматичСски ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ элСмСнты Ρ‡Π΅Ρ€Π΅Π· N сСкунд послС ΠΈΡ… добавлСния (TTL).
- ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ Π²Ρ‹ΡΠΎΠΊΡƒΡŽ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΈ массовом доступС (тысячи ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Π² сСкунду).
- ΠœΠΈΠ½ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ (`lock`) ΠΈΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ структуры.
- ΠšΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с ΠΈΡΡ‚Π΅ΠΊΡˆΠΈΠΌΠΈ элСмСнтами:
- НС Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ ΠΈΡ… Ρ‡Π΅Ρ€Π΅Π· Get.
- НС ΠΊΠΎΠΏΠΈΡ‚ΡŒ мусор Π² памяти.

---

β–ͺ️ ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡ:

- МоТно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ стандартныС ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ .NET (`ConcurrentDictionary`, Timer, Task, CancellationToken ΠΈ Ρ‚.Π΄.).
- НСльзя ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ внСшниС Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ Ρ‚ΠΈΠΏΠ° MemoryCache, Redis, LazyCache ΠΈ Π΄Ρ€.
- НуТно ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠΏΠΎΠ΄ большой Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΎΠΉ (ΠΌΠ½ΠΎΠ³ΠΎ ΠΊΠ»ΡŽΡ‡Π΅ΠΉ ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ).

---

β–ͺ️ Подсказки:

- Для ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎΠ³ΠΎ доступа ΠΏΠΎΠ΄ΠΎΠΉΠ΄Ρ‘Ρ‚ ConcurrentDictionary<TKey, ValueWithExpiry>.
- Для очистки ΡƒΡΡ‚Π°Ρ€Π΅Π²ΡˆΠΈΡ… Π΄Π°Π½Π½Ρ‹Ρ…:
- МоТно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΠΎΠ½ΠΎΠ²ΡƒΡŽ Π·Π°Π΄Π°Ρ‡Ρƒ (`Task`) с Ρ‚Π°ΠΉΠΌΠ΅Ρ€ΠΎΠΌ, которая пСриодичСски чистит старыС записи.
- ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Π³ΠΎΠ½ΠΊΠΈ состояний: ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΎΠΉ срока ΠΆΠΈΠ·Π½ΠΈ элСмСнта ΠΈ Π΅Π³ΠΎ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ΠΌ.

---

β–ͺ️ Π§Ρ‚ΠΎ оцСниваСтся:

- Π£ΠΌΠ΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ потокобСзопасныС структуры Π΄Π°Π½Π½Ρ‹Ρ….
- ΠŸΡ€ΠΎΠ΄ΡƒΠΌΠ°Π½Π½ΠΎΡΡ‚ΡŒ балансировки ΠΌΠ΅ΠΆΠ΄Ρƒ ΡΠΊΠΎΡ€ΠΎΡΡ‚ΡŒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ ΠΈ частотой очистки.
- ΠŸΡ€Π°Π²ΠΈΠ»ΡŒΠ½Π°Ρ Ρ€Π°Π±ΠΎΡ‚Π° со Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ ΠΆΠΈΠ·Π½ΠΈ (`TTL`).
- Чистота ΠΈ Π»Π°ΠΊΠΎΠ½ΠΈΡ‡Π½ΠΎΡΡ‚ΡŒ ΠΊΠΎΠ΄Π°.

---

β–ͺ️ Π Π°Π·Π±ΠΎΡ€ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠ³ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ:

β–ͺ️ Основная идСя:

- Π’ кэшС Ρ…Ρ€Π°Π½ΠΈΠΌ Π½Π΅ просто Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Π° ΠΏΠ°Ρ€Ρƒ (Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ + врСмя истСчСния).
- ΠŸΡ€ΠΈ Get(key):
- ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, истёк Π»ΠΈ элСмСнт.
- Если истёк β€” удаляСм Π΅Π³ΠΎ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ null ΠΈΠ»ΠΈ default.
- ΠŸΡ€ΠΈ Set(key, value):
- БохраняСм Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ + TTL.
- ΠžΡ‚Π΄Π΅Π»ΡŒΠ½Π°Ρ фоновая Π·Π°Π΄Π°Ρ‡Π° (`Task`) рСгулярно сканируСт кэш ΠΈ удаляСт ΡƒΡΡ‚Π°Ρ€Π΅Π²ΡˆΠΈΠ΅ элСмСнты.

β–ͺ️ Мини-ΠΏΡ€ΠΈΠΌΠ΅Ρ€ структуры:


using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

public class SmartCache<TKey, TValue>
{
private readonly ConcurrentDictionary<TKey, (TValue Value, DateTime Expiry)> _cache = new();
private readonly TimeSpan _ttl;
private readonly CancellationTokenSource _cts = new();

public SmartCache(TimeSpan ttl)
{
_ttl = ttl;
StartCleanupTask();
}

public void Set(TKey key, TValue value)
{
_cache[key] = (value, DateTime.UtcNow.Add(_ttl));
}

public TValue Get(TKey key)
{
if (_cache.TryGetValue(key, out var entry))
{
if (entry.Expiry > DateTime.UtcNow)
{
return entry.Value;
}
else
{
_cache.TryRemove(key, out _);
}
}
return default;
}

private void StartCleanupTask()
{
Task.Run(async () =>
{
while (!_cts.Token.IsCancellationRequested)
{
foreach (var key in _cache.Keys)
{
if (_cache.TryGetValue(key, out var entry) && entry.Expiry <= DateTime.UtcNow)
{
_cache.TryRemove(key, out _);
}
}
await Task.Delay(TimeSpan.FromSeconds(30), _cts.Token); // пСриодичСская очистка
}
});
}

public void Dispose()
{
_cts.Cancel();
}
}

πŸ“Œ Π’Π°ΠΆΠ½Ρ‹Π΅ ΠΌΠΎΠΌΠ΅Π½Ρ‚Ρ‹:

- Кэш ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½Ρ‹ΠΉ (`ConcurrentDictionary`) β€” доступ Π±Π΅Π· явных Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΎΠΊ.
- ΠŸΠ΅Ρ€ΠΈΠΎΠ΄ΠΈΡ‡Π΅ΡΠΊΠ°Ρ чистка Π½Π΅ ΠΌΠ΅ΡˆΠ°Π΅Ρ‚ основным опСрациям.
- Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΈΡΡ‚Ρ‘ΠΊΡˆΠΈΡ… элСмСнтов происходит "мягко" (Ρ‡Π΅Ρ€Π΅Π· ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ срока ΠΆΠΈΠ·Π½ΠΈ).
- Ѐоновая Π·Π°Π΄Π°Ρ‡Π° ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· CancellationToken.



tg-me.com/csharp_1001_notes/680
Create:
Last Update:

πŸ“Œ Π—Π°Π΄Π°Ρ‡Π°: "ВысоконагруТённый кэш с автоматичСской очисткой ΠΈ ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½Ρ‹ΠΌ доступом"

❗️УсловиС:

Π Π΅Π°Π»ΠΈΠ·ΡƒΠΉΡ‚Π΅ класс SmartCache<TKey, TValue> Π² .NET, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π΄ΠΎΠ»ΠΆΠ΅Π½:

- ΠŸΠΎΠ·Π²ΠΎΠ»ΡΡ‚ΡŒ бСзопасно Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ элСмСнты ΠΈΠ· кэша Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС (`Get`, `Set`).
- АвтоматичСски ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ элСмСнты Ρ‡Π΅Ρ€Π΅Π· N сСкунд послС ΠΈΡ… добавлСния (TTL).
- ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ Π²Ρ‹ΡΠΎΠΊΡƒΡŽ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΈ массовом доступС (тысячи ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Π² сСкунду).
- ΠœΠΈΠ½ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ (`lock`) ΠΈΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ структуры.
- ΠšΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с ΠΈΡΡ‚Π΅ΠΊΡˆΠΈΠΌΠΈ элСмСнтами:
- НС Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ ΠΈΡ… Ρ‡Π΅Ρ€Π΅Π· Get.
- НС ΠΊΠΎΠΏΠΈΡ‚ΡŒ мусор Π² памяти.

---

β–ͺ️ ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡ:

- МоТно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ стандартныС ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ .NET (`ConcurrentDictionary`, Timer, Task, CancellationToken ΠΈ Ρ‚.Π΄.).
- НСльзя ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ внСшниС Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ Ρ‚ΠΈΠΏΠ° MemoryCache, Redis, LazyCache ΠΈ Π΄Ρ€.
- НуТно ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠΏΠΎΠ΄ большой Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΎΠΉ (ΠΌΠ½ΠΎΠ³ΠΎ ΠΊΠ»ΡŽΡ‡Π΅ΠΉ ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ).

---

β–ͺ️ Подсказки:

- Для ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎΠ³ΠΎ доступа ΠΏΠΎΠ΄ΠΎΠΉΠ΄Ρ‘Ρ‚ ConcurrentDictionary<TKey, ValueWithExpiry>.
- Для очистки ΡƒΡΡ‚Π°Ρ€Π΅Π²ΡˆΠΈΡ… Π΄Π°Π½Π½Ρ‹Ρ…:
- МоТно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΠΎΠ½ΠΎΠ²ΡƒΡŽ Π·Π°Π΄Π°Ρ‡Ρƒ (`Task`) с Ρ‚Π°ΠΉΠΌΠ΅Ρ€ΠΎΠΌ, которая пСриодичСски чистит старыС записи.
- ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Π³ΠΎΠ½ΠΊΠΈ состояний: ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΎΠΉ срока ΠΆΠΈΠ·Π½ΠΈ элСмСнта ΠΈ Π΅Π³ΠΎ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ΠΌ.

---

β–ͺ️ Π§Ρ‚ΠΎ оцСниваСтся:

- Π£ΠΌΠ΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ потокобСзопасныС структуры Π΄Π°Π½Π½Ρ‹Ρ….
- ΠŸΡ€ΠΎΠ΄ΡƒΠΌΠ°Π½Π½ΠΎΡΡ‚ΡŒ балансировки ΠΌΠ΅ΠΆΠ΄Ρƒ ΡΠΊΠΎΡ€ΠΎΡΡ‚ΡŒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ ΠΈ частотой очистки.
- ΠŸΡ€Π°Π²ΠΈΠ»ΡŒΠ½Π°Ρ Ρ€Π°Π±ΠΎΡ‚Π° со Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ ΠΆΠΈΠ·Π½ΠΈ (`TTL`).
- Чистота ΠΈ Π»Π°ΠΊΠΎΠ½ΠΈΡ‡Π½ΠΎΡΡ‚ΡŒ ΠΊΠΎΠ΄Π°.

---

β–ͺ️ Π Π°Π·Π±ΠΎΡ€ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠ³ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ:

β–ͺ️ Основная идСя:

- Π’ кэшС Ρ…Ρ€Π°Π½ΠΈΠΌ Π½Π΅ просто Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Π° ΠΏΠ°Ρ€Ρƒ (Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ + врСмя истСчСния).
- ΠŸΡ€ΠΈ Get(key):
- ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, истёк Π»ΠΈ элСмСнт.
- Если истёк β€” удаляСм Π΅Π³ΠΎ ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ null ΠΈΠ»ΠΈ default.
- ΠŸΡ€ΠΈ Set(key, value):
- БохраняСм Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ + TTL.
- ΠžΡ‚Π΄Π΅Π»ΡŒΠ½Π°Ρ фоновая Π·Π°Π΄Π°Ρ‡Π° (`Task`) рСгулярно сканируСт кэш ΠΈ удаляСт ΡƒΡΡ‚Π°Ρ€Π΅Π²ΡˆΠΈΠ΅ элСмСнты.

β–ͺ️ Мини-ΠΏΡ€ΠΈΠΌΠ΅Ρ€ структуры:


using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

public class SmartCache<TKey, TValue>
{
private readonly ConcurrentDictionary<TKey, (TValue Value, DateTime Expiry)> _cache = new();
private readonly TimeSpan _ttl;
private readonly CancellationTokenSource _cts = new();

public SmartCache(TimeSpan ttl)
{
_ttl = ttl;
StartCleanupTask();
}

public void Set(TKey key, TValue value)
{
_cache[key] = (value, DateTime.UtcNow.Add(_ttl));
}

public TValue Get(TKey key)
{
if (_cache.TryGetValue(key, out var entry))
{
if (entry.Expiry > DateTime.UtcNow)
{
return entry.Value;
}
else
{
_cache.TryRemove(key, out _);
}
}
return default;
}

private void StartCleanupTask()
{
Task.Run(async () =>
{
while (!_cts.Token.IsCancellationRequested)
{
foreach (var key in _cache.Keys)
{
if (_cache.TryGetValue(key, out var entry) && entry.Expiry <= DateTime.UtcNow)
{
_cache.TryRemove(key, out _);
}
}
await Task.Delay(TimeSpan.FromSeconds(30), _cts.Token); // пСриодичСская очистка
}
});
}

public void Dispose()
{
_cts.Cancel();
}
}

πŸ“Œ Π’Π°ΠΆΠ½Ρ‹Π΅ ΠΌΠΎΠΌΠ΅Π½Ρ‚Ρ‹:

- Кэш ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½Ρ‹ΠΉ (`ConcurrentDictionary`) β€” доступ Π±Π΅Π· явных Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΎΠΊ.
- ΠŸΠ΅Ρ€ΠΈΠΎΠ΄ΠΈΡ‡Π΅ΡΠΊΠ°Ρ чистка Π½Π΅ ΠΌΠ΅ΡˆΠ°Π΅Ρ‚ основным опСрациям.
- Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΈΡΡ‚Ρ‘ΠΊΡˆΠΈΡ… элСмСнтов происходит "мягко" (Ρ‡Π΅Ρ€Π΅Π· ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ срока ΠΆΠΈΠ·Π½ΠΈ).
- Ѐоновая Π·Π°Π΄Π°Ρ‡Π° ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· CancellationToken.

BY C# 1001 notes


Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283

Share with your friend now:
tg-me.com/csharp_1001_notes/680

View MORE
Open in Telegram


C 1001 notes Telegram | DID YOU KNOW?

Date: |

Telegram is riding high, adding tens of million of users this year. Now the bill is coming due.Telegram is one of the few significant social-media challengers to Facebook Inc., FB -1.90% on a trajectory toward one billion users active each month by the end of 2022, up from roughly 550 million today.

C 1001 notes from no


Telegram C# 1001 notes
FROM USA