Я установил связку Console.WriteLine
s, и насколько я могу судить, ни один из них не вызывается, когда я запускаю следующее в .NET Fiddle.Как проверить, работает ли этот интервал?
using System;
using System.Net;
using System.Linq.Expressions;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Collections.Generic;
public class Program
{
private static readonly object locker = new object();
private static readonly string pageFormat = "http://www.letsrun.com/forum/forum.php?board=1&page={0}";
public static void Main()
{
var client = new WebClient();
// Queue up the requests we are going to make
var tasks = new Queue<Task<string>>(
Enumerable
.Repeat(0,50)
.Select(i => new Task<string>(() => client.DownloadString(string.Format(pageFormat,i))))
);
// Create set of 5 tasks which will be the at most 5
// requests we wait on
var runningTasks = new HashSet<Task<string>>();
for(int i = 0; i < 5; ++i)
{
runningTasks.Add(tasks.Dequeue());
}
var timer = new System.Timers.Timer
{
AutoReset = true,
Interval = 2000
};
// On each tick, go through the tasks that are supposed
// to have started running and if they have completed
// without error then store their result and run the
// next queued task if there is one. When we run out of
// any more tasks to run or wait for, stop the ticks.
timer.Elapsed += delegate
{
lock(locker)
{
foreach(var task in runningTasks)
{
if(task.IsCompleted)
{
if(!task.IsFaulted)
{
Console.WriteLine("Got a document: {0}",
task.Result.Substring(Math.Min(30, task.Result.Length)));
runningTasks.Remove(task);
if(tasks.Any())
{
runningTasks.Add(tasks.Dequeue());
}
}
else
{
Console.WriteLine("Uh-oh, task faulted, apparently");
}
}
else if(!task.Status.Equals(TaskStatus.Running)) // task not started
{
Console.WriteLine("About to start a task.");
task.Start();
}
else
{
Console.WriteLine("Apparently a task is running.");
}
}
if(!runningTasks.Any())
{
timer.Stop();
}
}
};
}
}
Я также ценю советы о том, как я могу упростить или исправить любую ошибочную логику в этом. Образец, который я пытаюсь сделать, это как
(1) Создание queueu из N задач
(2) Создать набор задач M, первый M из очереди элементы из (1)
(3) Запустите выполнение заданий M
(4) Через X секунд проверьте выполненные задачи.
(5) Для любой завершенной задачи сделайте что-нибудь с результатом, удалите задачу из набора и замените ее другой задачей из очереди (если она оставлена в очереди).
(6) Повторите (4) - (5) на неопределенный срок.
(7) Если у набора нет заданий, мы закончили.
но, возможно, есть лучший способ реализовать его, или, возможно, есть какая-то функция .NET, которая легко инкапсулирует то, что я пытаюсь сделать (веб-запросы параллельно с указанной максимальной степенью параллелизма).
Была ли причина, по которой вы выбрали этот подход, просто нажав задачи в ThreadPool? Не говоря о том, что вы ошибаетесь, мне просто интересно. –
Простой ActionBlock с конкретным DOP решит проблему –