我有一个.NET Windows服务,它有一个间隔设置为10秒的计时器。每隔10秒,它会向数据库查询要完成的任何工作,获取前3个工作项并处理它们。处理每个工作项所花费的时间取决于用户。它可能从几秒到几分钟不等。
我觉得10秒太短了。我选择了一个较短的间隔,因为用户正在等待完成该过程(他们在前端看到一个进度条),并且服务获取工作的速度越快越好。此外,随机选取了#个工作项目(三个)。
我的代码中有“锁定(this)”以防止一个线程踩到另一个线程。生产环境中的持续时间是否短暂10秒?
编辑:此外,我每次只挑选3件商品是否有意义。
答案 0 :(得分:1)
我目前正在处理这样的事情,主计时器从存储过程中获取每秒要做的工作(1000毫秒)。
但是,提取不仅限于X项(例如3) 我只是根据需要添加尽可能多的线程,让框架正确处理它们。
我试图以不需要使用任何lock
的方式解耦所有代码。
我保存到db所有日志信息,我有另一个计时器(间隔30分钟),最终获取错误并邮寄给我。
假设您将所有工作交给另一个不同于计时器的线程,那么1秒计时器应该没有问题。
答案 1 :(得分:1)
您的服务间隔应独立于UI。实现此目的的一种方法是为数据库中的每个工作项创建一个标记,将其标记为“新”,“正在进行中”或“已完成”。让您的服务一次拿起一件商品并将其标记为“在制品中”,做任何需要的事情,并在完成后将其标记为“已完成”。
然后,您的UI将轮询该表并根据需要更新每个最近修改过的行的状态。
通过这种方式,您的计时器间隔与UI延迟之外的任何考虑无关。您还可以在不牺牲效率的情况下运行多个服务线程(如果您一次处理一个项目,则三个线程可以处理三个项目,而不是单个线程获取三个项目),竞争条件很少或没有机会等等
另外,请务必在处理过程中禁用计时器,否则可能会使您的过程方法重入(自行中断)。
答案 2 :(得分:1)
...另外,我每次只挑选3件物品才有意义......
拥有大量物品可能会很危险。您有可能让项目进入队列的速度快于处理它们的速度。考虑如果超过三个项目每十秒排队一次会发生什么。您会开始发现项目需要处理的时间越来越长。
产生额外的线程或使用事件驱动的方法可能会更好。
答案 3 :(得分:0)
我想这取决于你的查询有多复杂。如果它是一个简单的查询,它会立即返回并且每10秒钟只由一个服务运行,我怀疑它会成为一个问题,但我对你的环境一无所知,所以不要抱我这么做。
如果您正在寻找另一种解决方案,您可以查看消息传递架构而不是轮询。
基本上在这种情况下,无论您将工作添加到数据库中的系统,都可以向您的服务发出消息,让它知道有工作要做。然后你的服务不需要轮询任何东西,只是坐着等待它需要检查数据库的通知。 或者,您可以在消息本身中包含要执行的工作,并让服务处理它并存储需要存储在数据库本身的内容。
如果您对消息传递感兴趣,请查看NServiceBus。它基本上是MSMQ的一个包装器,它将让您开启一个关于互连系统的全新思想世界。
选项真是无穷无尽。
答案 4 :(得分:0)
我会使用10秒的间隔 在用户进程完成时再做一次检查(以防止不必要的10秒等待)
您可以查看SQLDependency类来捕获数据库事件。这会更好,但实施起来有点困难。
有关SQLDependecy的更多信息,请查看此处:
http://www.codeproject.com/KB/database/chatter.aspx
答案 5 :(得分:0)
这是一个难以回答的问题;您的生产环境的硬件配置可能比您的比较环境更大,因此您的队列处理速度可能比当前值更快。
如果您不想猜测,请尝试实施基于队列的winservice。该服务将读取MSMQ队列并及时获取工作项并进行处理。因此,如果您仍然需要处理工作项目,您只需要询问该队列,并且您可以按照您想要的任何频率执行此操作,比方说,1秒钟。
最重要的事情是为了确保在你还有工作的时候不要去做更多的工作项目。
顺便说一句,您应该阅读:Why lock(this) is bad。