0

У меня есть чекер прокси, я хочу сделать его многопоточным. Как это правильно организовать? У меня была идея засунуть все строки с проксями в список, этот список поделить на равные списки кол-во которых зависит от кол-ва потоков, и в каждый поток загружать свой список. Минус такого велосипеда в том что если один поток закончит работу раньше другого, то он просто завершится а не поможет другому. Вот и думаю, как правильно организовать многопоточность?

  • Возможно, вам подойдет этот способ, только если вы возмете мою реализацию (не важно, какую именно), и у вас десктопное приложение, не забудьте покинуть UI контекст синхронизации перед запуском. А вообще ваша задача - чистой воды шаблон проектирования Producer/Consumer, туда и копать. С асинхронным программированием то знакомы async/await? – aepot Jul 12 '21 at 17:07

1 Answers1

0

Не думаю, что ручное управление потоками нужно в этой задаче.

Кажется, вам нужно опрашивать по кругу заданный список хостов, лимитируя максимальное количество одновременных запросов. Я делал что-то похожее с использованием System.Timers.Timer:

    const int MAX_PARALLEL_DEGREE = 5;
    const int TRY_EXECUTE_INTERVAL_MS = 100;
public static void Main() 
{
    int currParallelDegree = 0;

    var args = new ConcurrentQueue<string>(
        from ch in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" select ch.ToString()
    );

    var timer = new System.Timers.Timer(TRY_EXECUTE_INTERVAL_MS);

    timer.Elapsed += async (sender, e) => {
        var p = Interlocked.Increment(ref currParallelDegree);

        if (p <= MAX_PARALLEL_DEGREE) {
            if (args.TryDequeue(out var st)) {
                try {
                    Console.WriteLine($">>{st} Parallel is {p}");
                    await Task.Delay(1000);
                    Console.WriteLine($"<<{st} Parallel is {p}");
                }
                finally {
                    args.Enqueue(st);
                }
            }
            else {
                Console.WriteLine($"No available items. Parallel is {p}");
            }     
        }
        else {
            Console.WriteLine($"Skip due to limiting concurrency. Parallel is {p}");
        }

        Interlocked.Decrement(ref currParallelDegree);
    };

    timer.Start();
    Console.ReadLine();
    timer.Stop();

Минусы решения - "прогрев" при начале выполнения (не сразу используется весь допустимый уровень параллелизма) и теоретическая возможность напрасного пропуска тика. Мне обе проблемы были совершенно не критичны.