鉴于将作为Windows服务运行的C#控制台应用程序,有两种应用程序入口点。第一个明显的方法是static void Main
方法。此方法的部分工作是安装扩展ServiceBase
的内容然后运行它以获取其OnStart
方法。还有像Topshelf这样的更高级别的工具可以帮助您避免低级ServiceBase
实施,但最终仍然有2个潜在的应用程序入口点:static void Main
和某种OnStart
方法
此类服务的应用程序根目录是否应该在服务的OnStart
方法中组合,或者早于static void Main
的一部分?
似乎在服务的OnStart
方法中进行编写(并在OnStop
方法中销毁/处理它)可能会有一个优势,因为重新启动服务会构成一个新的应用程序根。我在这里看到的唯一真正的缺点是,如果我使用像Topshelf这样的工具,我不能使用DI容器来获取我的Service类的实例。然而,这可能不是一个真正的劣势。尽管如此,我读到的大多数应用程序在Main
期间构成根,而不是在OnStart
期间,我不确定原因。
一种方法真的比另一种方法好,还是取决于哪种方式,我的问题实际上是基于意见的方法?
答案 0 :(得分:2)
我认为这不是一个事实而是一个事实,但我更喜欢在服务构建期间撰写,然后使用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;
}
}
}
<强> composition.cs 强>
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();
}
}
<强> imyservice.cs 强>
public interface IMyService
{
void Start();
void Stop();
}
我在这里看到的唯一真正的缺点是,如果我使用像Topshelf这样的工具,我不能使用DI容器来获取我的Service类的实例
这是事实,但您无需访问program.cs代码,只需访问MyService代码,该代码将代表您服务的实际“核心”代码。
同样当你停止服务时你会实际杀死它(除非你暂停它),所以无论你是否把它放在“onStart()”内,它都会再次执行。
像往常一样,恕我直言。 :)