Parallel.ForEach仅在代码尚未运行时才在启动时执行两次?

时间:2012-12-04 01:01:49

标签: c# multithreading parallel-processing task-parallel-library

我正在开发一个Windows服务,我尝试使用Parallel.ForEach来生成唯一的定时线程。问题是,如果我在VS中单独保留代码几个小时,或者如果我停止服务几个小时并重新开始任何操作 - 初始启动代码执行两次。这是服务的OnStart调用的静态void的片段。

Parallel.ForEach(urls, url =>
                    {
                        PageGrabber pagegrab = new PageGrabber(url);
                        if (url.Type.ToLower() == "http")
                        {
                            pagegrab.Elapsed += (obj, e) =>
                                {
                                    pagegrab.CheckNormal();
                                };
                            pagegrab.CheckNormal();
                        }
                        else
                        {
                            pagegrab.Elapsed += (obj, e) =>
                            {
                                pagegrab.CheckXML();
                            };
                            pagegrab.CheckXML();
                        }
                    }
                    );

如果我直接使用Threads,这非常有用,但我真的想更新一下这段代码。重复执行立即发生。 PageGrabber对象非常简单,因为它只是使用WebClient将HTML或XML下载为字符串 - 非常无聊。

2 个答案:

答案 0 :(得分:3)

我认为问题在于您已Elapsed订阅pageGrabber.Elapsed +=...事件 该事件有可能被提升或不提高。 因此,在某些情况下,如果事件被引发,您的方法将被调用两次,否则将被调用一次。

我认为您不能通过更改并行实现(使用任务数组而不是Parallel.Foreach)来解决此问题。它可能导致问题不常发生,这是并行编程中非常糟糕的症状。你不应该让问题通过让他们的先决条件变得更难而消失!你应该完全删除它们!

答案 1 :(得分:0)

所以mehrandvd走在了正确的道路上。在创建使用System.Timers.Timer的类的实例时,它会立即触发Elapsed事件,因为没有正确设置Interval属性。因此:

pagegrab.Elapsed += (obj, e) =>
                        {
                            pagegrab.CheckXML();
                        };
                        pagegrab.CheckXML();

在一段时间内没有发生任何事情时导致重复执行,因为正确设置了Interval的类的实例不再在内存中。我的愚蠢 - 现在都修好了。感谢所有的意见和建议。