【问题标题】:Processing long-running operations from a windows service处理来自 Windows 服务的长时间运行的操作
【发布时间】:2010-03-05 21:43:27
【问题描述】:

编辑(再次):让我简化我的问题。我有一个 Windows 服务,它使用以下方法公开一些 WCF 端点:

int ExecuteQuery(string query) {
   // asynchronously execute query that may take 1 second to 20 minutes
   return queryId;
}

string GetStatus(int queryId) {
   // return the status of the query (# of results so far, etc)
}

实现ExecuteQuery 方法的最佳方式是什么?我应该打电话给ThreadPool.QueueUserWorkItem 来查询吗?

请注意,执行查询背后的实际工作是由负载平衡的黑盒完成的。我希望能够同时进行多个查询。

类比是一个同时下载多个文件的网络浏览器,而您有一个可以跟踪每个文件状态的下载管理器。

【问题讨论】:

    标签: c# multithreading windows-services queue long-running-processes


    【解决方案1】:

    看看Microsoft Message Queuing (MSMQ)

    Microsoft 消息队列 (MSMQ) 技术使在不同时间运行的应用程序能够跨异构网络和可能暂时离线的系统进行通信。 MSMQ 提供有保证的消息传递、高效的路由、安全性和基于优先级的消息传递。它可用于实现异步和同步消息传递方案的解决方案。

    很高兴知道 Windows Communication Foundation (WCF) 可以利用 MSMQ 提供的队列服务。

    【讨论】:

    • 我的印象是 MSMQ 需要相当多的基础架构。此外,在这种情况下,“谁”将实际执行查询? MSMQ 只是中介吗?
    • @intoorbit:MSMQ 需要安装 Windows 组件,但让它工作起来相当容易。此外,当你开始使用它时,你会免费获得一堆很棒的功能。是的,MSMQ 只是传递消息,您仍然需要手动处理它们。它本身不能进行实际处理,但它消除了在应用程序和服务之间建立通信基础设施的负担。
    • 我编辑了我的问题以降低沟通渠道的重要性。但是,我确实计划检查 MSMQ,看看它是否可以成为我解决方案的一部分。即使是临时的、与时间相关的、非关键的请求,您认为值得吗?
    • @intoorbit:如果您没有从 MSMQ 中获得任何好处,那就没有。我不会鼓励你使用一些东西只是为了很酷。您可以使用简单的 WCF 通道。重新处理事情的方式,在大多数情况下,只需调用ThreadPool.QueueUserWorkItem 将工作项排队就可以了。它也绝对可以在 Windows 服务中使用。我不确定您对 X 名工人的确切含义是什么?您的意思是单个请求在 X 个不同的服务器上处理,或者请求在 X 个服务器之间进行负载平衡或其他什么?
    • 我想我一定提出了一个过于复杂的问题。我用一些代码再次改写了它,以便对此进行最后一次尝试。我的意思是,如果我“执行查询”,它将由一些负载平衡的黑盒处理,结果开始流回给我。我想立即向用户返回一个“状态 ID”,然后一次进行多个查询。真的,这很像 Firefox 同时下载 X 文件,您的下载管理器会告诉您每个文件的距离。
    【解决方案2】:

    这要么是一个技巧问题,要么是一个简单的问题...ThreadPool.QueueUserWorkItem 是当您想要同时执行一段代码时最简单的方法。我相信你已经知道了,所以从技术上讲你已经回答了你自己的问题。

    因此,如果这不是一个技巧问题,那么您是在问如何在 ThreadPool.QueueUserWorkItem 中传递查询?

    【讨论】:

    • 我想我可能在这里大声思考,让我的问题看起来比实际更复杂。有很多“建议”说“不要过度使用 ThreadPool,尤其是对于长时间运行的任务”。我只是想看看是否有针对我的问题的任何建议。
    • 有人反对在 ThreadPool 中使用“长时间运行”的任务,因为如果一个任务正在等待另一个任务执行某些工作,并且该任务正在等待在同一个 ThreadPool 中执行,但是线程池已满,那么排队的任务可能永远不会被执行,你会遇到死锁。即使是短期任务也可能发生这种情况。我认为如果有人遇到这个问题,那么他们只是错误地设计了他们的程序......
    【解决方案3】:

    我将 Windows 服务用于非常相似的任务,并且效果很好。我使用数据库表对请求和响应进行排队,因为它为我提供了一个持久队列,可以从远程 ASP.Net 应用程序通过网络访问,并通过事务进行并发控制。

    每当传入请求需要服务时,计时器上的主管线程会生成工作人员。我使用单独的数据库表进行配置和控制,这样我就可以管理服务并暂停应用程序的主管,而无需让服务核心运行。登录到单独的表是查看 Web 应用程序和本地管理应用程序正在发生的事情的便捷方式。

    我不会将 ThreadPool 用于长时间运行的线程,而是创建一个在其自己的线程中运行的工作类,并使用回调方法来更新主管的进度和完成状态。

    【讨论】:

    • 是的......这几乎就是我打算做的,就我而言,我什至不需要将状态持久化到数据库中。我问这个问题是因为我认为所有生产者/消费者类型的代码都如此频繁地完成,必须有一些已经存在的代码或模式可以利用。
    【解决方案4】:

    除了 MSMQ 答案之外,如果您担心未来的可扩展性,您可以考虑使用企业服务总线 (ESB) 来处理这些事情。查看 NServiceBus 获取一个 .NET 示例。

    【讨论】:

      【解决方案5】:

      我会使用 WWF (4.0):

      您可以启动可以在几台机器上处理的长时间运行的事务,并行执行任务,故障支持,友好的编码,您可以使用 appfabric 管理它,它是免费的...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-06
        • 2012-04-10
        • 1970-01-01
        相关资源
        最近更新 更多