C# 何时在windows服务中组合应用程序根目录
给定一个将作为windows服务运行的C#控制台应用程序,有两个应用程序入口点。第一个明显的方法是C# 何时在windows服务中组合应用程序根目录,c#,windows-services,topshelf,compositionroot,C#,Windows Services,Topshelf,Compositionroot,给定一个将作为windows服务运行的C#控制台应用程序,有两个应用程序入口点。第一个明显的方法是静态void Main方法。此方法的一部分工作是安装扩展了ServiceBase的东西,然后运行它以获取要调用的OnStart方法。还有更高级别的工具,如Topshelf,可以帮助您避免较低级别的ServiceBase实现,但最终还是会得到两个潜在的应用程序入口点:static void Main,以及某种OnStart方法 此类服务的应用程序根目录是否应该在服务的OnStart方法中组成,或者早于
静态void Main
方法。此方法的一部分工作是安装扩展了ServiceBase
的东西,然后运行它以获取要调用的OnStart
方法。还有更高级别的工具,如Topshelf,可以帮助您避免较低级别的ServiceBase
实现,但最终还是会得到两个潜在的应用程序入口点:static void Main
,以及某种OnStart
方法
此类服务的应用程序根目录是否应该在服务的OnStart
方法中组成,或者早于作为静态void Main
的一部分组成
似乎在服务的OnStart
方法中组合(并在OnStop
方法中销毁/处理)可能有好处,因为重新启动服务将组合一个新的应用程序根。我在这里看到的唯一真正的缺点是,如果我使用像Topshelf这样的工具,我就不能使用DI容器来获取我的服务类的实例。再说一次,这可能不是真正的劣势。不过,我读到的大多数应用程序都是在Main
期间编写根目录的,而不是在OnStart
期间编写的,我不知道为什么
一种方法真的比另一种好吗,还是取决于它,而我的问题真的是基于观点的吗?我认为这更像是一种观点而不是事实,但我更喜欢在构建服务时编写,然后使用OnStart()激活我以前编写的服务。这是我(与Topshelf)通常的工作方式。例如: program.cs
public class Program
{
private static ILifetimeScope _scope;
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
public static void Main(string[] args)
{
try
{
XmlConfigurator.Configure();
// configure composition
_scope = CompositionRoot.CreateScope();
HostFactory.Run(x =>
{
x.UseLog4Net();
x.UseAutofacContainer(_scope);
x.Service<IMyService>(svc =>
{
svc.ConstructUsingAutofacContainer();
svc.WhenStarted(tc => tc.Start());
svc.WhenStopped(tc =>
{
tc.Stop();
_scope.Dispose();
});
});
x.RunAsNetworkService();
x.StartManually();
});
}
catch (Exception e)
{
Log.Error("An error occurred during service construction.", e);
throw;
}
}
}
internal class CompositionRoot
{
public static ILifetimeScope CreateScope()
{
var builder = new ContainerBuilder();
builder.RegisterType<MyService>().As<IMyService>().SingleInstance();
// other things you want to register
return builder.Build();
}
}
public interface IMyService
{
void Start();
void Stop();
}
我在这里看到的唯一真正的缺点是,如果我使用像Topshelf这样的工具,我就不能使用DI容器来获取我的服务类的实例
这是真的,但是您不需要访问program.cs代码,只需要访问MyService代码,它将代表您服务的实际“核心”代码
此外,当您停止服务时,您实际上会终止它(除非暂停它),因此该组合将再次执行,无论您是否将其放入“onStart()”中
和往常一样,伊姆霍:) Main是唯一的进程条目,因此它更像是一个“进程范围”的构造函数。一个服务程序/流程可以承载多个服务实例,而不仅仅是一个实例。每个服务实例构造函数在每个进程生命周期中只应调用一次,但可以重复调用OnStart/OnStop。现在,我真的不明白应用程序根是什么意思,也不明白您想要编写什么,但我认为您应该将每个服务初始化与实例初始化联系起来。所以,如果您使用ServiceBase,它应该以某种方式与它的构造函数相关联。两种情况下的入口点都是Main()。发生的唯一额外的事情是服务管理器的OnStart()调用,您通常启动一个线程来做一些有用的事情。延迟任何事情都没有意义,它不会优化任何东西,在Main()开始运行后,OnStart()调用会很快发生。@HansPassant那么当windows服务重新启动时,Main()方法会再次被调用吗?如果是这样的话,那么我误解了什么,你是对的,这个问题无关紧要。