gpt4 book ai didi

multithreading - 在单独的线程中运行 Windows 服务并使用 autofac 进行 DI

转载 作者:行者123 更新时间:2023-12-03 12:45:43 25 4
gpt4 key购买 nike

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

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

我真的不确定如何为 worker 类设置 Autofac。目前,当我在工作类的“Execute”方法中使用 DbContext 时,我收到错误消息,告诉我 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();
}

worker 类(Class):

    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.....
}
}
}

最佳答案

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

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

在你的情况下,这意味着你需要改变你的设计,因为 NotificationService 被解析一次并且它的依赖项在另一个线程上被重用。这是 no-no在依赖注入(inject)领域。

这是另一种设计:

// 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) .

关于multithreading - 在单独的线程中运行 Windows 服务并使用 autofac 进行 DI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17356776/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com