加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 关于使用并行Web的任务队列获取代码的问题

发布时间:2020-12-15 21:22:29 所属栏目:百科 来源:网络整理
导读:所以我已经有了这段代码,可以从REST api深入研究 XML文档的层次结构.我 posted earlier得到关于如何使其递归的建议,然后我继续并将其变为parralel. 首先,我被它的运行速度所震撼 – 它在不到12秒的时间内就下载了318个XML文档,相比之下,单线程超过10分钟 –
所以我已经有了这段代码,可以从REST api深入研究 XML文档的层次结构.我 posted earlier得到关于如何使其递归的建议,然后我继续并将其变为parralel.

首先,我被它的运行速度所震撼 – 它在不到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;
        }

解决方法

只是随便,我不打扰管理任务列表,所有锁定和NumTasks()方法的代码.使用 CountdownEvent会更简单,开始时是线程安全的.只需在创建新任务时递增它,并在任务完成时递减它,就像你现在正在做但没有锁定.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读