How to check if this interval works?

I installed a bunch Console.WriteLine, and as far as I can tell, none of them get called when I run the following in the .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();
                }
            }

        };
    }
}

I would also like to know how I can simplify or correct any erroneous logic in this. The template I'm trying to do is similar to

(1) Create a queueu of N tasks

(2) Create a set of tasks from M, the first M from the selected elements from (1)

(3) Start the execution of tasks M

(4) After X seconds, check completed assignments.

(5) For any completed task, do something with the result, remove the task from the set, and replace it with another task from the queue (if it is left in the queue).

(6) Repeat (4) - (5) endlessly.

(7) If the set has no assignments, we are done.

, , , , - .NET, , (- parallelism).

+4
2

, , Parallel.For Parallel.ForEach:

Parallel.For(0, 50, new ParallelOptions() { MaxDegreeOfParallelism = 5 }, (i) =>
{
     // surround with try-catch
     string result;
     using (var client = new WebClient()) {
          result = client.DownloadString(string.Format(pageFormat, i));
     }
     // do something with result
     Console.WriteLine("Got a document: {0}", result.Substring(Math.Min(30, result.Length)));
});

( 5 ). , , , .

UPDATE. , , :

Parallel.For(0, 50, new ParallelOptions() { MaxDegreeOfParallelism = 5 },  
(i) =>
{
    // surround with try-catch
    var watch = Stopwatch.StartNew();
    string result;
    using (var client = new WebClient()) {
         result = client.DownloadString(string.Format(pageFormat, i));
    }
    // do something with result
    Console.WriteLine("Got a document: {0}", result.Substring(Math.Min(30, result.Length)));
    watch.Stop();
    var sleep = 2000 - watch.ElapsedMilliseconds;
    if (sleep > 0)
          Thread.Sleep((int)sleep);
});
+3

. .

Microsoft Reactive Framework (NuGet "System.Reactive" ) .

- :

var query =
    Observable
        .Range(0, 50)
        .Select(i => string.Format(pageFormat, i))
        .Select(u => Observable.Using(
            () => new WebClient(),
            wc => Observable.Start(() => new { url = u, content = wc.DownloadString(u) })))
        .Merge(5);

IDisposable subscription = query.Subscribe(x =>
{
    Console.WriteLine(x.url);
    Console.WriteLine(x.content);
});

, subscription.Dispose();

+2

Source: https://habr.com/ru/post/1661808/


All Articles