2014-12-29 3 views
1

다음 웹 사이트에서 HTML 문자열을 다운로드하는 다음 코드가 있습니다.한 번에 최대 3 개의 스레드 제한

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<string> URLsToProcess = new List<string>() 
     { 
      "http://www.microsoft.com", 
      "http://www.stackoverflow.com", 
      "http://www.google.com", 
      "http://www.apple.com", 
      "http://www.ebay.com", 
      "http://www.oracle.com", 
      "http://www.gmail.com", 
      "http://www.amazon.com", 
      "http://www.yahoo.com", 
      "http://www.msn.com" 
     }; 



     List<Task<string>> tURLs = new List<Task<string>>(); 

     foreach (string url in URLsToProcess) 
     { 
      Task<string> t = DownloadStringAsTask(new Uri(url)); 
      tURLs.Add(t); 
     } 

     Console.WriteLine("waiting now"); 

     Task.WaitAll(tURLs.ToArray()); 

     Console.WriteLine("download all done"); 
     foreach (Task<string> t in tURLs) 
      Console.WriteLine(t.Result); 
    } 


    static Task<string> DownloadStringAsTask(Uri address) 
    { 
     TaskCompletionSource<string> tcs = 
      new TaskCompletionSource<string>(); 
     WebClient client = new WebClient(); 
     client.DownloadStringCompleted += (sender, args) => 
     { 
      if (args.Error != null) 
       tcs.SetException(args.Error); 
      else if (args.Cancelled) 
       tcs.SetCanceled(); 
      else 
       tcs.SetResult(args.Result); 
     }; 
     client.DownloadStringAsync(address); 
     return tcs.Task; 
    } 
} 

이 코드를 사용하면 10 개의 다른 스레드를 실행하여 10 개의 다른 URL에서 데이터를 다운로드 할 수 있습니다. 한 번에 최대 3 개의 스레드로 제한하고 싶습니다. 다른 요청은 스레드 중 하나가 해제 될 때까지 대기해야합니다. 이 제한 사항을 추가하는 방법에 대한 아이디어가 있습니까?

+0

당신이 스레드에 대한 제어를 할 경우'Task'은 *하지 *는'Thread', 당신은 사용해야하는'ThreadPool' http://msdn.microsoft.com/en-us /library/3dasc8as.aspx –

+0

이 제한 사항에는 세마포를 사용해야합니다. –

+0

자신 만의 스레드 풀을 만들려고하십니까? – dotctor

답변

1

Data ParallelismTask Parallelism을 참조하십시오. 여기 병렬 LINQ를 사용할 수 있습니다

한 번에 실행 스레드의 수를 제한하는 SemaphoreSlim 클래스를 사용할 수
var URLsToProcess = new List<string> 
        { 
         "http://www.microsoft.com", 
         "http://www.stackoverflow.com", 
         "http://www.google.com", 
         "http://www.apple.com", 
         "http://www.ebay.com", 
         "http://www.oracle.com", 
         "http://www.gmail.com", 
         "http://www.amazon.com", 
         "http://www.yahoo.com", 
         "http://www.msn.com" 
        }; 

Console.WriteLine("waiting now"); 

string[] tURLs = URLsToProcess 
    .AsParallel() 
    .WithDegreeOfParallelism(3) 
    .Select(uri => this.DownloadStringAsTask(new Uri(uri)).Result) 
    .ToArray(); 

Console.WriteLine("download all done"); 
foreach (string t in tURLs) 
{ 
    Console.WriteLine(t); 
} 
+0

URL 중 하나에서 예외가 발생하면 어떻게됩니까? – BKS

1

. 클래스 프로그램 {

static void Main(string[] args) 
    { 

     List<string> URLsToProcess = new List<string>() 
     { 
      "http://www.microsoft.com", 
      "http://www.stackoverflow.com", 
      "http://www.google.com", 
      "http://www.apple.com", 
      "http://www.ebay.com", 
      "http://www.oracle.com", 
      "http://www.gmail.com", 
      "http://www.amazon.com", 
      "http://www.yahoo.com", 
      "http://www.msn.com" 
     }; 

     SemaphoreSlim ss = new SemaphoreSlim(3); //limit 3 threads at a time 

     List<Task<string>> tURLs = new List<Task<string>>(); 


     foreach (string url in URLsToProcess) 
     { 
      //Task<string> t = DownloadStringAsTask(new Uri(url)); 
      //tURLs.Add(t); 
      tURLs.Add((Task<string>)Task.Run(() => 
      { 
       DownloadStringAsTask(new Uri(url)); 
       ss.Release(); 
      })); 
     } 

     Console.WriteLine("waiting now"); 

     Task.WaitAll(tURLs.ToArray()); 

     Console.WriteLine("download all done"); 
     foreach (Task<string> t in tURLs) 
      Console.WriteLine(t.Result); 

     Console.ReadLine(); 
    } 



    static Task<string> DownloadStringAsTask(Uri address) 
    { 
     TaskCompletionSource<string> tcs = 
      new TaskCompletionSource<string>(); 
     WebClient client = new WebClient(); 
     client.DownloadStringCompleted += (sender, args) => 
     { 
      if (args.Error != null) 
       tcs.SetException(args.Error); 
      else if (args.Cancelled) 
       tcs.SetCanceled(); 
      else 
       tcs.SetResult(args.Result); 
     }; 

     client.DownloadStringAsync(address); 

     return tcs.Task; 
    } 
} 
관련 문제