static void Main(string[] args) { var uriDatabase = new UriDatabase(); var errorDatabase = new MemoryDatabase<string, long>(); GenerateReport(uriDatabase.SoftDump(), errorDatabase.ToDictionary()); var feeder = new FeedStream<ThreadedWorker>(); feeder.Feed(args.Skip(1).Select(s => new Uri(s))); var requesters = new List<HttpRequestStream<ThreadedWorker>>(); for (int i = 0; i < int.Parse(args.ElementAt(0)); i++) { requesters.Add(new HttpRequestStream<ThreadedWorker>(uriDatabase)); } var funnel = new FunnelStream<ContentLoad, Uri, ThreadedWorker>(); var parser = new ParserStream<ThreadedWorker>(); feeder.ReturnFeed = parser; parser.ReturnFeed = funnel; requesters.ForEach(stream => stream.ReturnFeed = feeder); funnel.ReturnFeeds = requesters; feeder.OnError += (sender, eventArgs) => CollectError(errorDatabase, eventArgs.GetException()); parser.OnError += (sender, eventArgs) => CollectError(errorDatabase, eventArgs.GetException()); funnel.OnError += (sender, eventArgs) => CollectError(errorDatabase, eventArgs.GetException()); requesters.ForEach(stream => stream.OnError += (sender, eventArgs) => CollectError(errorDatabase, eventArgs.GetException())); parser.Start(); funnel.Start(); requesters.ForEach(stream => stream.Start()); feeder.Start(); var timer = new Timer(2000); timer.Elapsed += (sender, eventArgs) => { var dump = uriDatabase.SoftDump(); var errors = errorDatabase.ToDictionary(); GenerateReport(dump, errors); }; timer.Start(); Console.ReadLine(); }