C#使用semaphore 管理异步下载请求
 var semaphor = new Semaphore(50, 50);  // We allow at most 50 threads for crawling
            var resultPins = new List<Pin>();  // Results stored here
            foreach (var pin in new HashSet<string>(pinIdList))
            {
                semaphor.WaitOne();
                Console.Write(">");
                var pinClient = new WebClient();
                pinClient.DownloadStringCompleted += (sender, ex) =>
                {
                    var html = ex.Result.Replace("\n", "");
                    pinClient.Dispose();
                    lock (pinIdList)
                    {
                         // do some post-processing and write back the results
                    }
                    Console.Write("<");
                    semaphor.Release();
                };
                pinClient.DownloadStringAsync(new Uri(string.Format("http://pinterest.com/pin/{0}/", pin)));
            }
            for (int i = 0; i < 50; i++) semaphor.WaitOne();    // Wait until the last thread ends.
            semaphor.Dispose();
            Console.WriteLine();




