2013-03-30 39 views
0

我有以下要求:多線程C#5.0

有一些網址,應該下載。

  1. 只有3網址可在同時下載
  2. 的過程。如果這3個網址,一個(或多個)完成 - 需要從陣列得到一個可用的網址
  3. 如果一個(或多個)從這3個網址在X時間內並未完成 - 需要取消此網址
  4. 如果網址數組已完成 - 我們將等待完成所有當前任務,並且只有一個從主要方法開始。

如何在C#5.0上做到這一點?我嘗試做以下操作:

class Program 
{ 
    static Stopwatch sw = Stopwatch.StartNew(); 

    static void Main(string[] args) 
    { 
     List<Task> tasks = new List<Task>(); 
     string[] urls = new string[] { "http://site1.ru", "http://www.site2.com", "http://site3.com", "http://site4.ru" }; 
     foreach (var url in urls) 
     { 
      var task = AsyncVersion(url); 
      tasks.Add(task); 
     } 

     Task.WaitAll(tasks.ToArray()); 
    } 

    static async Task AsyncVersion(string url) 
    { 
     var webRequest = WebRequest.Create(url); 
     Console.WriteLine(
      "Перед вызовом webRequest.GetResponseAsync(). Thread Id: {0}, Url : {1}", 
      Thread.CurrentThread.ManagedThreadId, url); 
     var webResponse = await webRequest.GetResponseAsync(); 
     Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url, 
      webResponse.ContentLength, sw.ElapsedMilliseconds, 
      Thread.CurrentThread.ManagedThreadId); 

    } 
} 

哪些部分我不明白:

  1. 如何控制每個線程混凝土(沒有隻等待一個接一個或所有的任務,但每個線程)
  2. 多久了每道工序都執行...

回答

2

這看起來像Parallel.ForEach()

一份理想的工作

您可以通過參數設置併發限制,然後在等待響應太長時間後使用WebRequest.Timeout屬性進行保留。

事情是這樣的:

Parallel.ForEach(
    urls, 
    new ParallelOptions { MaxDegreeOfParallelism = 3 }, 
    url => 
    { 
     try 
     { 
      var request = WebRequest.Create(url); 
      request.Timeout = 10000; // milliseconds 
      var response = request.GetResponse(); 
      // handle response 
     } 
     catch (WebException x) 
     { 
      // timeout or some other problem with the request 
     } 
     catch (Exception x) 
     { 
      // make sure this Action doesn't ever let an exception 
      // escape as that would stop the whole ForEach loop 
     } 
    } 
); 

Parallel.ForEach()調用將阻塞調用線程,直到所有的網址已被處理。
然而,它將使用多達MaxDegreeOfParallelism線程來運行該工作。