Подтвердить что ты не робот

.NET Custom Threadpool с отдельными экземплярами

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

Изменить: Мне нужно как можно быстрее развести эти сайты для информации, используя отдельный поток для каждого сайта, чтобы дать мне возможность контролировать количество потоков, работающих на каждом сайте в любой момент времени. (не более 2-3)

Спасибо Roey

4b9b3361

Ответ 1

Я полагаю, что Smart Thread Pool может это сделать. Создается класс ThreadPool, поэтому вы должны иметь возможность создавать и управлять отдельными конкретными экземплярами сайта по мере необходимости.

Ответ 2

Ami bar написал отличный пул интеллектуальных потоков, который может быть создан.

посмотрите здесь

Ответ 4

Использование BlockingCollection может использоваться в качестве очереди для потоков. Вот реализация этого. Обновлено в 2018-04-23:

public class WorkerPool<T> : IDisposable
{
    BlockingCollection<T> queue = new BlockingCollection<T>();
    List<Task> taskList;
    private CancellationTokenSource cancellationToken;
    int maxWorkers;
    private bool wasShutDown;

    int waitingUnits;

    public WorkerPool(CancellationTokenSource cancellationToken, int maxWorkers)
    {
        this.cancellationToken = cancellationToken;
        this.maxWorkers = maxWorkers;
        this.taskList = new List<Task>();
    }
    public void enqueue(T value)
    {
        queue.Add(value);
        waitingUnits++;
    }
    //call to signal that there are no more item
    public void CompleteAdding()
    {
        queue.CompleteAdding();          
    }

    //create workers and put then running
    public void startWorkers(Action<T> worker)
    {
        for (int i = 0; i < maxWorkers; i++)
        {
            taskList.Add(new Task(() =>
            {
                string myname = "worker " + Guid.NewGuid().ToString();

                try
                {
                    while (!cancellationToken.IsCancellationRequested)
                    {                     
                        var value = queue.Take();
                        waitingUnits--;
                        worker(value);
                    }
                }
                catch (Exception ex) when (ex is InvalidOperationException)  //throw when collection is closed with  CompleteAdding method. No pretty way to do this.
                {
                    //do nothing
                }
            }));
        }

        foreach (var task in taskList)
        {
            task.Start();
        }
    }

    //wait for all workers to be finish their jobs
    public void await()
    {
        while (waitingUnits >0 || !queue.IsAddingCompleted)
            Thread.Sleep(100);

        shutdown();
    }

    private void shutdown()
    {
        wasShutDown = true;
        Task.WaitAll(taskList.ToArray());            
    }

    //case something bad happen dismiss all pending work
    public void Dispose()
    {
        if (!wasShutDown)
        {
            queue.CompleteAdding();
            shutdown();
        }
    }
}

Тогда используйте как это:

WorkerPool<int> workerPool = new WorkerPool<int>(new CancellationTokenSource(), 5);

workerPool.startWorkers(value =>
{
    log.Debug(value);
});
//enqueue all the work
for (int i = 0; i < 100; i++)
{
    workerPool.enqueue(i);
}
//Signal no more work
workerPool.CompleteAdding();

//wait all pending work to finish
workerPool.await();

Вы можете иметь столько опросов, сколько хотите, просто создавая новые объекты WorkPool.

Ответ 5

Эта бесплатная библиотека nuget здесь: CodeFluentRuntimeClient имеет класс CustomThreadPool, который можно повторно использовать. Он очень настраиваемый, вы можете изменить приоритет пулов, число, состояние COM-квартиры, даже имя (для отладки), а также культуру.

Ответ 6

Другой подход заключается в использовании конвейера потока данных. Я добавил этот более поздний ответ, потому что я считаю, что Dataflows гораздо лучше подходит для решения подобных проблем, проблемы с несколькими пулами потоков. Они обеспечивают более гибкий и структурированный подход и могут легко масштабироваться по вертикали.

Вы можете разбить ваш код на один или несколько блоков, затем связать их с потоками данных, а затем позволить механизму потоков данных распределять потоки в соответствии с доступностью ЦП и памяти.

Я предлагаю разбить на 3 блока: один для подготовки запроса к странице сайта, один для доступа к странице сайта и последний для анализа данных. Таким образом, медленный блок (get) может иметь больше потоков, выделенных для компенсации.

Вот как бы выглядела установка Dataflow:

var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };

prepareBlock.LinkTo(get, linkOptions);
getBlock.LinkTo(analiseBlock, linkOptions);

Данные будут prepareBlock из prepareBlock в getBlock а затем в analiseBlock. Интерфейсы между блоками могут быть любого класса, просто должны быть одинаковыми. Смотрите полный пример на Dataflow Pipeline

Использование потока данных будет что-то вроде этого:

 while ...{
    ...
    prepareBlock.Post(...); //to send data to the pipeline
 }
 prepareBlock.Complete(); //when done
 analiseBlock.Completion.Wait(cancellationTokenSource.Token); //to wait for all queues to empty or cancel