4

我有一个启动计时器功能的 Windows 服务。该函数在数据库中查询新记录,然后为找到的每条新记录调用 Web 服务。

现在要求此服务在每个时间间隔为多个数据库执行此操作。

该服务目前如下所示:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.ServiceProcess;

namespace MiManager.TicketLogger {

  public partial class TicketLogger : ServiceBase {

    private TicketLoggerSettings _settings;
    private List<DbConnectionSettings> _connections;

    public TicketLogger() {
      InitializeComponent();
    }

    protected override void OnStart(string[] args) {

      var helpers = new MiManager.TicketLogger.Helpers();
      _settings = helpers.GetTicketLoggerSettings();
      _connections = helpers.GetDbConnectionSettings();

      if (_settings.LogVerbose == true) evlgTicketLogger.WriteEntry("Registry entries obtained", EventLogEntryType.Information, 100);
      tmrTicketLogger.Interval = _settings.ServiceInterval;
      tmrTicketLogger.Elapsed += new System.Timers.ElapsedEventHandler(TimerElapsed);
      tmrTicketLogger.Enabled = true;
      tmrTicketLogger.Start();
    }

    protected override void OnStop() {
      tmrTicketLogger.Stop();
      tmrTicketLogger.Enabled = false;
    }

    private void TimerElapsed(Object sender, System.Timers.ElapsedEventArgs e) {
      try {
        tmrTicketLogger.Stop();

        Core core = new MiManager.TicketLogger.Core();
        List<Message> messages = core.LogTickets(_settings);
        foreach (var message in messages) {
          evlgTicketLogger.WriteEntry(message.Text, message.EntryType, message.ErrorCode);
        }
        if (_settings.LogVerbose == true) {
          evlgTicketLogger.WriteEntry("Ticket logging complete", EventLogEntryType.Information, 101);
        }
      }
      catch (Exception ex) {
        evlgTicketLogger.WriteEntry(ex.ToString(), EventLogEntryType.Error, 400);
      }
      finally {
        tmrTicketLogger.Start();
      }
    }

  }

}

现在我需要调整服务以获取多个连接字符串,并为每个数据库连接调用 TimerElapsed 函数中的 LogTickets 函数。

当前推荐的在 Windows 服务中执行此操作的方法是什么?

在多年前的一个项目中,我为每个要处理的连接手动创建了一个新线程,但我确定现在有更好的方法吗?

它是 Async/Await 的好用例吗?如果我这样做,核心类中的所有方法也必须是异步的吗?

使用 Parallel.ForEach 之类的东西会更好吗?

4

2 回答 2

4

在服务器端,async方法为您提供可伸缩性。但是,听起来您的服务不需要扩展太多,因此async不会真正给您带来任何优势。

使用 Parallel.ForEach 之类的东西会更好吗?

如果您现有的代码是同步的(并且您不需要async提供给您的可伸缩性),那很好。如果您将所有内容更改为,您的服务减少资源密集型(并且可能稍微快一点)async- 但这将需要相当多的代码更改(AFAICS)几乎没有好处。

如果您确实想探索Win32 服务中的代码,我建议使用我的typeasync创建单个主线程。只要您的代码是正确异步的(例如,使用EF6 进行异步 DB 调用异步 Web 调用),那么您应该只需要一个线程。AsyncContextThreadasyncHttpClient

于 2013-10-21T17:40:10.863 回答
0

很大程度上取决于您的解决方案的复杂性需求、您希望如何处理数据以及您当前的 .NET 框架版本是什么,因为有很多方法可以做到这一点。

您可以执行以下操作,其中 HandleConnection 是您处理连接的函数:

var parallelTask = Task.Factory.StartNew(() => Parallel.ForEach(_connections, connection => HandleConnection(connection)));

我建议花几分钟时间阅读并行性、.NET 4.5 中的新异步/等待功能以及 MSDN 上的任务。有许多不同的延续选项可用于任务。探索什么适合您的需求。

数据并行

使用 Async 和 Await 进行异步编程

任务工厂

于 2013-10-21T17:02:36.053 回答