【问题标题】:Converting threaded app to service将线程应用程序转换为服务
【发布时间】:2012-11-27 14:44:28
【问题描述】:

我目前有一个应用程序,它基本上是约 10 个“LongRunning”Tasks 的包装器。每个线程都应该无限期地运行,但有时它们会锁定或崩溃,有时包装器应用程序会自发退出(我还没有能够追踪到它)。此外,包装应用程序目前只能为一个用户运行,并且该用户必须是重新启动线程或重新启动整个应用程序的用户。

我目前有一个监视器实用程序,可以让我知道线程何时停止工作,以便可以手动重新启动它们,但我想改为自动重新启动它们。我还希望每个人都可以使用包装器来检查线程的状态,并让线程即使在包装器没有运行时也能运行。

基于这些目标,我想我想将线程分离成一个 Windows 服务,并将包装器转换为可以连接到服务以检查其状态并对其进行操作的东西。

我该怎么做呢?这是一个合理的架构吗?我应该把每个线程变成一个单独的服务,还是应该有一个单一的多线程服务?

编辑:所有任务都记录到同一组输出文件(通过TextWriter.Synchronized(StreamWriter)),我希望保持这种行为。
他们目前也都共享相同的数据库连接,这意味着我需要让他们都同意在必要时同时关闭连接。但是,如果将它们分开,则它们可以各自使用自己的数据库连接,而我无需担心同步。我实际上怀疑这一步是当前的失败点之一,因此将其拆分是一件好事。

【问题讨论】:

  • 线程是否相互交互?他们应该共享静态资源吗?
  • @SLaks - 编辑添加他们共享的资源。

标签: c# multithreading windows-services


【解决方案1】:

如果可能,我建议您留在一个多线程服务中。只需确保在触发服务停止时正确处理线程。将刹车标志放在需要大量执行时间的代码块中。这样,您将使您的服务响应停止事件。记录任何异常并确保等待所有线程退出,直到服务最终停止。这将阻止您在多个线程中运行相同的“任务”。

维护一项服务最终比维护多项服务更容易。

如果您需要一些可以相互运行或不相互运行的单独功能,则拆分为多个服务是合理的。

【讨论】:

  • 使用这个模型,我将如何处理我想从集合中重新启动一个无响应线程的锁定场景?
  • 从完整的服务角度来看这是不可能的。重新启动应该重新启动所有线程。但是,您可以在主服务线程中将每个线程声明为私有并监视它们。如果您检测到特定线程无响应,只需中止它并启动新线程,或者您可以决定重新启动完整服务。
  • 不幸的是,由于其他架构妥协,同一应用程序中的每个线程都使用相同的数据库连接,如果该连接无响应,则无法检查线程是否正在工作。因此,监视器实用程序具有自己的连接。是否可以向服务发送消息告诉它“重新启动线程 X”?
  • 您可以检查线程是否处于活动状态 msdn.microsoft.com/en-us/library/… 。另一种方法是在特定线程完成某些工作(如连接到数据库)时记录 DataTime。关于从服务外部重新启动。是的,我有可能做过类似的事情,但这需要额外的工作。您必须在您的服务中写入 tcp/ip 或 wcf 服务器并从客户端(外部应用程序)接收命令。当然,也可以按需重新启动特定线程。
  • 你启发我去找this,我认为这应该解决重启线程的问题。将其与您的建议相结合应该是一个完美可行的解决方案。
【解决方案2】:

我认为将线程移至 Windows 服务不会消除任何问题。服务还是会随机崩溃,线程还是会随机退出。

我假设您的长时间运行的任务实现了一种工作循环。将该循环的主体包装在 try-catch 中并记录所有异常。不要重新抛出它们,以免任务退出。检查日志以查找错误。

【讨论】:

  • 它不会解决任何潜在的问题,不。但是,自动杀死并重新启动它们,并将控制包装器的 UI 与工作人员分开,这将是可行的。
  • 我的主要观点是转移到服务并没有帮助。你怎么看?
  • 除非有一种方法可以从另一个应用程序中自动终止和重新启动一个应用程序中的线程,否则将其移至服务会有所帮助。我知道如何杀死并重新启动服务。显然,找到并修复错误会更好,但我不能保证线程在等待某些东西时不会被锁定(这是我们数据库反复出现的问题) .我可以告诉的唯一方法是查看工作是否正在完成。
  • 杀死服务不会导致服务中断吗?在我看来,您可能只想在单个线程死亡或无响应时才重新启动它。或者更好的是,每个线程都有一个进程并重新启动该进程。这可能是最可靠的。无论如何,您不需要 Windows 服务。你可以只使用一个子进程并保留一个句柄来检测它的死亡。
  • 杀死它并在不久后恢复它不会有任何影响。但是只重新启动一个线程将是理想的。问题是应用程序本身无法检测到线程何时因数据库连接丢失而挂起,因为它需要该连接来判断线程是否已挂起。请参阅我对 Gregor 的回答的评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-15
  • 1970-01-01
  • 2013-06-17
  • 2013-02-12
  • 1970-01-01
相关资源
最近更新 更多