Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Last active March 30, 2026 19:06
Show Gist options
  • Select an option

  • Save sunmeat/aef66bac2754e8555a3208bd690948f5 to your computer and use it in GitHub Desktop.

Select an option

Save sunmeat/aef66bac2754e8555a3208bd690948f5 to your computer and use it in GitHub Desktop.
приклад на пул потоків
using System.Text;
class Program
{
static readonly object fileLock = new object();
static void RoastDuck(object? state)
{
var dishName = (string?)state;
if (dishName == "Запіканка з качки")
{
Console.WriteLine("Запікаємо качку...");
Thread.Sleep(3000);
Console.WriteLine("КАЧКА ГОТОВА");
}
}
static void Main()
{
Console.OutputEncoding = Encoding.UTF8;
Console.WriteLine("Програма почала виконання...");
// https://learn.microsoft.com/uk-ua/dotnet/api/system.threading.threadpool.setminthreads?view=net-9.0
ThreadPool.SetMaxThreads(500, 500); // за замовчуванням - 32767 робочих, 1000 потоків вводу-виводу
ThreadPool.SetMinThreads(20, 20); // мінімум 20 робочих і 20 потоків вводу-виводу (якщо не встановити, буде по 2-5 одночасно, щоб не перевантажувати систему)
// фактична кількість запущених потоків може бути меншою, якщо немає навантаження
// робочий потік — це потік, який виконує обчислювальні задачі, такі як обробка даних або виконання алгоритмів
// потік вводу-виводу — очікує завершення операції вводу-виводу, наприклад, читання з файлу або надсилання даних мережею. такі потоки зазвичай блокуються до завершення операції (без задачі, асинхронного очікування та тривалого навантаження важко відстежити)
// пул потоків обирає, який потік запустити, залежно від типу задачі: обчислювальні задачі виконуються робочими потоками, а операції вводу-виводу у файл, БД або мережу — потоками вводу-виводу
var resetEvent = new ManualResetEvent(false);
// окремий потік, який оновлюватиме статистику
var statisticsThread = new Thread(UpdateThreadStatistics);
statisticsThread.IsBackground = true; // потік не блокуватиме завершення програми
statisticsThread.Start();
int totalTasks = 200;
int completedTasks = 0;
// додаємо одну задачу в пул потоків
ThreadPool.QueueUserWorkItem(RoastDuck, "Запіканка з качки");
// додаємо задачі на обчислення
for (int i = 1; i <= totalTasks / 2; i++)
{
long countUntil = 40000000L + i;
int numberOfTask = i;
ThreadPool.QueueUserWorkItem(state =>
{
long sum = 0;
long threadId = Thread.CurrentThread.ManagedThreadId;
for (long j = 1; j < countUntil; j++)
sum += j;
// виводимо результат у термінал
Console.WriteLine($"Задача #{numberOfTask}. Результат обчислень: {sum}, номер потоку: {threadId}");
// потікобезпечно збільшуємо кількість завершених задач
Interlocked.Increment(ref completedTasks);
// коли всі задачі завершені, сигналізуємо про це основному потоку
if (completedTasks == totalTasks)
{
resetEvent.Set();
}
});
}
// додаємо ще задач для роботи з потоками
for (int i = totalTasks / 2; i <= totalTasks; i++)
{
int numberOfTask = i;
ThreadPool.QueueUserWorkItem(state =>
{
string dataToWrite = new string('A', 10 * 1024/* * 1024*/); // рядок у 1MB, тут обережно :)
long threadId = Thread.CurrentThread.ManagedThreadId;
lock (fileLock)
{
File.AppendAllText("task_output.txt", dataToWrite);
}
// виводимо результат у термінал
Console.WriteLine($"Задача #{numberOfTask}. Дані записано у файл. Потік #{threadId}");
// потікобезпечно збільшуємо кількість завершених задач
Interlocked.Increment(ref completedTasks);
// коли всі задачі завершені, сигналізуємо про це основному потоку
if (completedTasks == totalTasks)
{
resetEvent.Set();
}
});
}
resetEvent.WaitOne();
Console.WriteLine("Усі задачі завершені.");
}
private static void UpdateThreadStatistics()
{
while (true)
{
int availableWorkerThreads, ioThreads;
ThreadPool.GetAvailableThreads(out availableWorkerThreads, out ioThreads);
Console.Title = $"У пулі: {availableWorkerThreads}, працює: {ThreadPool.ThreadCount}";
Thread.Sleep(15);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment