Last active
March 30, 2026 19:06
-
-
Save sunmeat/aef66bac2754e8555a3208bd690948f5 to your computer and use it in GitHub Desktop.
приклад на пул потоків
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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