2011-08-16 5 views
4

このコードは、REST APIからのXML文書の階層構造にドリルダウンするためのコードです。私はposted earlier再帰的にする方法のアドバイスを得るために、私は先に進み、それをparralelにしました。並列Webのタスクキューを使用しているコードについての質問

最初に、私はどのくらい速く走ったのかについて驚いていました。これは、318個のXML文書をわずか12秒でプルダウンしました。これは、10分を超えるシングルスレッドに比べて - 私はそれほど多くは期待しませんでした。それは本当に良いと思われるので、これにいくつかキャッチですか?

第2に、私はこのコードが共通のパターンを実装していると思われますが、おそらくは "慣用的な"方法ではないと考えています。 2つの別々のロックオブジェクトを使って、「プロデューサ - コンシューマキュー」が発生しています。私はこれを行うことができるより標準的な方法はありますか?

コード。

 public class ResourceGetter 
     { 
      public ResourceGetter(ILogger logger, string url) 
      { 
       this.logger = logger; 
       this.rootURL = url; 
      } 
      public List<XDocument> GetResources() 
      { 
       GetResources(rootURL); 
       while (NumTasks() > 0) RemoveTask().Wait(); 
       return resources; 
      } 
      void GetResources(string url) 
      { 
       logger.Log("Getting resources at " + url); 
       AddTask(Task.Factory.StartNew(new Action(() => 
       { 
        var doc = XDocument.Parse(GetXml(url)); 
        if (deserializer.CanDeserialize(doc.CreateReader())) 
        { 
         var rl = (resourceList)deserializer.Deserialize(doc.CreateReader()); 
         foreach (var item in rl.resourceURL) 
         { 
          GetResources(url + item.location); 
         } 
        } 
        else 
        { 
         logger.Log("Got resource for " + url); 
         AddResrouce(doc); 
        } 
       }))); 
      } 
      object resourceLock = new object(); 
      List<XDocument> resources = new List<XDocument>(); 
      void AddResrouce(XDocument doc) 
      { 
       lock (resourceLock) 
       { 
        logger.Log("add resource"); 
        resources.Add(doc); 
       } 
      } 
      object taskLock = new object(); 
      Queue<Task> tasks = new Queue<Task>(); 
      void AddTask(Task task) 
      { 
       lock (taskLock) 
       { 
        tasks.Enqueue(task); 
       } 
      } 
      Task RemoveTask() 
      { 

       lock (taskLock) 
       { 
        return tasks.Dequeue(); 
       } 
      } 
      int NumTasks() 
      { 
       lock (taskLock) 
       { 
        logger.Log(tasks.Count + " tasks left"); 
        return tasks.Count; 
       } 
      } 
      ILogger logger; 
      XmlSerializer deserializer = new XmlSerializer(typeof(resourceList)); 
      readonly string rootURL; 
     } 

答えて

1

私は、タスクリスト、すべてのロック、およびNumTasks()メソッドを管理するためのコードは気にしません。最初にスレッドセーフであるCountdownEventを使用する方が簡単です。新しいタスクを作成するときにそれを増やし、タスクが終了したときにそれを減らします。今のようなものですが、ロックなしのものです。

関連する問題