2013-03-30 3 views
0

Je les exigences suivantes:multithreading en C# 5.0

Il y a tableau de urls, qui doit être téléchargé.

  1. Seuls 3 urls peuvent être en cours de téléchargement en même temps
  2. Si un (ou plusieurs) de ces 3 urls sont terminés - besoin d'obtenir la prochaine URL sans tableau
  3. si un (ou plusieurs) de ces 3 urls ne sont pas terminés pendant X temps - besoin d'annuler cette url
  4. Si le tableau d'urls est terminé - nous attendons pour terminer toutes les tâches en cours et un seul va notre méthode principale.

Comment faire sur C# 5.0? J'essaie de faire ce qui suit:

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); 

    } 
} 

Quelles sont les parties que je ne comprends pas:

  1. Comment contrôler chaque béton de fil (sans attendre que l'un par l'une ou l'ensemble des tâches, mais chaque thread)
  2. Depuis combien de temps chaque processus exécutons ...

Répondre

2

Cela ressemble à un travail idéal pour Parallel.ForEach()

Vous pouvez définir la limite de concurrence par l'intermédiaire d'un paramètre, puis utiliser la propriété WebRequest.Timeout pour la libération après avoir attendu trop longtemps une réponse.

Quelque chose comme ceci:

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 
     } 
    } 
); 

L'appel à Parallel.ForEach() bloquera le thread appelant jusqu'à ce que tous les urls ont été traitées.
Il utilisera cependant jusqu'à MaxDegreeOfParallelism threads pour exécuter le travail.