1

我正在尝试使用Parallel.ForEach生成唯一定时线程的Windows服务。问题在于,如果我将代码单独留在VS中几个小时,或者如果我停止服务几个小时并启动任何备份 - 初始启动代码将执行两次。这是服务的OnStart调用的静态void的片段。仅当代码尚未运行时,Parallel.ForEach才会在启动时执行两次?

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

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

+0

您发布的哪部分代码是“最初启动代码”?还是那个地方? – svick

+0

缺少的部分是它读取包含URL的文本文件的部分,并使用它们创建“url”对象。它在try catch块中。获取URL,创建一个URL对象,将其添加到URL类型列表,然后是foreach循环 - 就是这样。这是真正的基本,这是什么让我这样做。这也很难调试,因为它只发生在大约6个小时内没有任何东西被触碰。 – kpcrash

+0

重复执行是否发生为对来自多个(几乎)同时线程的请求的响应?或者它是否在一个受控环境中响应一个请求而发生?即你确定封闭的方法没有被调用2x?我在发布的代码中看不到会导致问题的任何内容。 –

回答

3

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

我不认为你可以通过改变并行实现来解决这个问题(使用任务数组而不是Parallel.Foreach)。这可能会导致问题发生频率降低,这在并行编程中是非常糟糕的症状。你不应该让这些问题通过使他们的前提变得更加困难而消失!你应该完全删除它们!

+0

我不同意 - 因此对于设置已过期事件的替代方法有何建议?在这种情况下 - 对象中的System.Timers.Timer需要在它自己的Interval上运行。 – kpcrash

+0

@kpcrash我对你的PageGrabber类以及Elapsed事件的责任一无所知。 – mehrandvd

0

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

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

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

相关问题