【问题标题】:Questions about code using Task queue for parallel web gets关于使用 Task queue for parallel web 获取代码的问题
【发布时间】:2011-08-16 01:57:42
【问题描述】:

所以我有这段代码可以从 REST api 深入了解 XML 文档的层次结构。我posted earlier 获得有关如何使其递归的建议,然后我继续将其设为并行。

首先,我对它的运行速度感到震惊——它在不到 12 秒的时间内下载了 318 个 XML 文档,而单线程则超过 10 分钟——我真的没想到会获得那么多。这有什么问题吗,因为它看起来好得令人难以置信?

其次,我怀疑这段代码正在实现一种通用模式,但可能是以一种非“惯用”的方式。我发生了一种“生产者-消费者队列”,有两个单独的锁定对象。有没有更标准的方法可以做到这一点?

代码。

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

【问题讨论】:

    标签: c# multithreading multitasking


    【解决方案1】:

    顺便说一句,我不会为管理任务列表、所有锁定和 NumTasks() 方法的代码而烦恼。使用CountdownEvent 会更简单,它一开始是线程安全的。只需在创建新任务时增加它,并在任务完成时减少它,就像你现在正在做的那样,但没有锁定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多