Ответ 1
Я полагаю, что Smart Thread Pool может это сделать. Создается класс ThreadPool, поэтому вы должны иметь возможность создавать и управлять отдельными конкретными экземплярами сайта по мере необходимости.
Какой самый рекомендуемый .NET-поток для .NET, который может иметь отдельные экземпляры, т.е. более одного потока для каждого приложения? Мне нужен неограниченный размер очереди (создание искателя), и вам нужно параллельно запускать отдельный поток для каждого сайта, который я сканирую.
Изменить: Мне нужно как можно быстрее развести эти сайты для информации, используя отдельный поток для каждого сайта, чтобы дать мне возможность контролировать количество потоков, работающих на каждом сайте в любой момент времени. (не более 2-3)
Спасибо Roey
Я полагаю, что Smart Thread Pool может это сделать. Создается класс ThreadPool, поэтому вы должны иметь возможность создавать и управлять отдельными конкретными экземплярами сайта по мере необходимости.
Ami bar написал отличный пул интеллектуальных потоков, который может быть создан.
посмотрите здесь
Спросите Джона Скита: http://www.yoda.arachsys.com/csharp/miscutil/
Параллельные расширения для .Net(TPL) должны работать намного лучше, если вы хотите большое количество параллельных запущенных задач.
Использование 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.
Эта бесплатная библиотека nuget здесь: CodeFluentRuntimeClient имеет класс CustomThreadPool, который можно повторно использовать. Он очень настраиваемый, вы можете изменить приоритет пулов, число, состояние COM-квартиры, даже имя (для отладки), а также культуру.
Другой подход заключается в использовании конвейера потока данных. Я добавил этот более поздний ответ, потому что я считаю, что 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