我正在开发一个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下载为字符串 - 非常无聊。
答案 0 :(得分:3)
我认为问题在于您已Elapsed
订阅pageGrabber.Elapsed +=...
事件
该事件有可能被提升或不提高。
因此,在某些情况下,如果事件被引发,您的方法将被调用两次,否则将被调用一次。
我认为您不能通过更改并行实现(使用任务数组而不是Parallel.Foreach
)来解决此问题。它可能导致问题不常发生,这是并行编程中非常糟糕的症状。你不应该让问题通过让他们的先决条件变得更难而消失!你应该完全删除它们!
答案 1 :(得分:0)
所以mehrandvd走在了正确的道路上。在创建使用System.Timers.Timer的类的实例时,它会立即触发Elapsed事件,因为没有正确设置Interval属性。因此:
pagegrab.Elapsed += (obj, e) =>
{
pagegrab.CheckXML();
};
pagegrab.CheckXML();
在一段时间内没有发生任何事情时导致重复执行,因为正确设置了Interval的类的实例不再在内存中。我的愚蠢 - 现在都修好了。感谢所有的意见和建议。