2013-03-30 38 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线程来运行该工作。