3

我正在尝试创建一个长时间运行的 Windows 服务,因此我需要在单独的线程上运行实际的工作程序类,以避免在我右键单击并选择 Windows 服务中的启动时出现“服务未及时响应”错误经理。

工人类(“NotificationProcess”)有大量的依赖关系,我正在使用 Autofac 来满足这些。

我真的不确定如何为工人阶级设置 Autofac。目前,当我在工作类的“执行”方法中使用它时,我收到错误消息,告诉我 DbContext 已被释放。

我想我正在寻找如何编写 Windows 服务并为具有 autofac 满足的依赖项的工作类使用新线程。

我用谷歌搜索,找不到任何这样的例子。

任何建议都会很棒。

这是我到目前为止所得到的......

程序.cs:

    static class Program
{
    static void Main()
    {
        using (var container = ServiceStarter.CreateAutoFacContainer())
        {
            var service = container.Resolve<NotificationService>();
            if (Environment.UserInteractive)
            {
                service.Debug();
            }
            else
            {
                ServiceBase.Run(container.Resolve<NotificationService>());
            }
        }

服务类:

public partial class NotificationService : ServiceBase
{
    private NotificationProcess _app;
    readonly ILifetimeScope _lifetimeScope;

    public NotificationService(ILifetimeScope lifetimeScope)
    {
        _lifetimeScope = lifetimeScope;
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        _app = _lifetimeScope.Resolve<NotificationProcess>();
        _app.Start();
    } 

工人阶级:

    public class NotificationProcess
{
    private Thread _thread;

    private readonly IBankService _bankService;
    private readonly IRateService _rateService;
    private readonly IEmailService _emailService;
    private readonly IRateChangeSubscriberService _rateChangeSubscriberService;
    private readonly IRateChangeNotificationService _rateChangeNotificationService;
    private readonly ILogManager _logManager;

    public NotificationProcess(IBankService bankService, ILogManager logManager, IRateService rateService, IEmailService emailService, 
        IRateChangeSubscriberService rateChangeSubscriberService, IRateChangeNotificationService rateChangeNotificationService)
    {
        _bankService = bankService;
        _rateService = rateService;
        _emailService = emailService;
        _rateChangeSubscriberService = rateChangeSubscriberService;
        _rateChangeNotificationService = rateChangeNotificationService;
        _logManager = logManager;
    }

    public void Start()
    {
        _thread = new Thread(new ThreadStart(Execute));
        _thread.Start();
    }

    public void Execute()
    {
        try
        {
            var rateChangeToNotify = _rateService.GetRateChangesForNotification();

            foreach (var rateChange in rateChangeToNotify)
            {
                 //do whatever business logic.....
            }
        }
    }
4

1 回答 1

4

答案其实很简单:使用范围!您应该执行以下操作:

  1. DbContext使用 LifetimeScope 生活方式注册应在请求或操作期间存在的所有服务(例如)。您的 Windows 服务中通常会有一个计时器。每个“脉冲”都可以视为一个请求。
  2. 在每个请求开始时开始一个生命周期范围。
  3. 在该范围内,从对象图中解析根对象并调用其方法。
  4. 处置范围。

在您的情况下,这意味着您需要更改设计,因为NotificationService已解决一次,并且它的依赖关系在另一个线程上重用。这是依赖注入领域的禁忌

这是另一种设计:

// This method is called on a background thread 
// (possibly in a timely manner)
public void Run()
{
    try
    {
        using (var scope = container.BeginLifetimeScope())
        {
            var service = scope.Resolve<NotificationService>();
            service.Execute();
        }
    }
    catch (Exception ex)
    {
        // IMPORTANT: log exception. 
        // Not logging an exception will leave us in the dark.
        // Not catching the exception will kill our service 
        // because we run in a background thread.
    }
}

使用生命周期范围可以让您DbContext为每个请求获得一个新鲜的,它甚至可以让您并行运行请求(每个请求都有自己的DbContext)。

于 2013-06-28T09:02:44.063 回答