C# 将线程化应用程序转换为服务

C# 将线程化应用程序转换为服务,c#,multithreading,windows-services,C#,Multithreading,Windows Services,我目前有一个应用程序,它基本上是~10“LongRunning”任务的包装器。每个线程都应该无限期地运行,但有时它们会锁定或崩溃,有时包装器应用程序会自动退出(我还没能找到)。此外,包装器应用程序当前只能为一个用户运行,该用户必须是重新启动线程或重新启动整个应用程序的用户 我目前有一个监视实用程序,让我知道线程何时停止工作,以便可以手动重新启动它们,但我想自动重新启动它们。我还希望每个人都可以使用包装器来检查线程的状态,并且即使包装器没有运行,线程也可以运行 基于这些目标,我想我希望将线程分离到

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

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

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

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

编辑:所有任务都记录到同一组输出文件中(通过
TextWriter.Synchronized(StreamWriter)
),我希望保持这种行为。

它们目前也共享相同的数据库连接,这意味着我需要让它们都同意在必要时同时关闭连接。但是,如果将它们分开,它们可以各自使用自己的数据库连接,我就不需要担心同步问题。实际上,我怀疑这一步是当前的失败点之一,因此将其拆分将是一件好事。

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


我假设长期运行的任务实现了一种工作循环。在try-catch中包装该循环的主体,并记录所有异常。不要重新播放它们,以便任务永远不会退出。检查日志以查找bug。

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

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


如果您需要一些单独的功能,这些功能可以在一起运行,也可以不在一起运行,那么将其拆分为多个服务是合理的。

线程是否相互交互?他们应该共享静态资源吗?@SLaks-编辑以添加他们共享的资源。它不会修复任何潜在问题,不会。但是,它可以自动终止并重新启动它们,并将控件包装器的UI与工作程序分离。我的主要观点是,移动到服务并没有帮助。你是怎么想的?除非有一种方法可以从另一个应用程序中自动终止并重新启动一个应用程序中的线程,否则将其移动到一个服务将有所帮助。我知道如何终止和重新启动服务。显然,找到并修复bug会更好,但我无法保证线程在等待某个东西时没有锁定(这是我们的数据库经常出现的问题)。我能判断的唯一方法是看工作是否正在完成。终止服务不会导致服务中断吗?在我看来,您可能只想在单个线程死亡或无响应时重新启动它。或者更好的做法是,每个线程都有一个进程,然后重新启动该进程。这可能是最可靠的。;无论如何,您不需要windows服务。您可以使用一个子进程并保留一个句柄来检测它的死亡。杀死它并在不久后将其恢复不会有任何影响。但只要重新启动一个线程就很理想了。问题是,应用程序本身无法检测到线程何时由于数据库连接丢失而挂起,因为它需要该连接来判断线程是否挂起。请参阅我对Gregor答案的评论。使用此模型,我将如何处理锁定场景,即我希望从集合中重新启动一个无响应线程?从完整服务的角度来看,这是不可能的。重新启动应该重新启动所有线程。但是,您可以在主服务线程内将每个线程声明为私有线程并监视它们。如果您检测到SPCEIC线程没有响应,只需中止它并启动新线程,或者您可以决定重新启动完整的服务。不幸的是,由于其他架构方面的缺陷,同一应用程序中的每个线程都使用相同的数据库连接,如果连接没有响应,那么就无法检查线程是否正在工作。因此,monitor实用程序具有自己的连接。是否可以向服务发送一条消息,告诉它“重新启动线程X”?您可以检查线程是否处于活动状态。另一种方法是在特定线程完成某些工作(如连接到数据库)时记录数据时间。关于从服务外部重新启动。是的,这是可能的,我已经做了类似的事情,但它将需要额外的工作。您必须在服务中写入tcp/ip或wcf服务器,并从客户端(外部应用程序)接收命令。当然,按需重新启动特定的线程也是可能的。你启发我去寻找,我认为这应该解决重新启动线程的问题。结合你的建议应该是一个完全可行的解决方案。