c# - 如何让服务根据服务运行情况动态 Action

标签 c# asp.net vb.net

嗨, friend 们,我试图让我的服务动态运行......我已经为我的服务设置了大约 2 分钟的时间,如果假设它正在做大量的工作意味着它将超过 2 分钟的时间限制,那么我们需要如果工作未决则检查服务条件意味着我们需要运行该实例直到完成

所以我已经在谷歌搜索上尝试了下面的代码......我有方法需要在下面的服务中合作,任何人都可以帮助我

 public static void StartService(string serviceName, int timeoutMilliseconds)
   {
  ServiceController service = new ServiceController(serviceName);
  try
   {
   TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

    service.Start();
    service.WaitForStatus(ServiceControllerStatus.Running, timeout);
   }
   catch
  {
  // ...
  }
 }

截至目前,我正在按照逻辑执行此操作

  protected override void OnStart(string[] args)
    {
        // my service name 
        Workjob("FTSCSVGenerator");
        // ad 1: handle Elapsed event and CsvGenFromDatabase is method which i have to executed
        timerjob.Elapsed += new ElapsedEventHandler(CsvGenFromDatabase);
       // ad 2: set interval to 1 minute (= 60,000 milliseconds)
      timerjob.Interval = Convert.ToDouble(DueTime);
      //  ////ad 3: enabling the timer
      timerjob.Enabled = true;
      eventLog1.WriteEntry("my service started");
    }

    protected override void OnStop()
    {           
        eventLog1.WriteEntry("my service stopped");
    }


    private void Workjob(string servicename )
    {
        ServiceController servicecsv = new ServiceController(servicename);


         if ((servicecsv.Status.Equals(ServiceControllerStatus.Stopped)) || (servicecsv.Status.Equals(ServiceControllerStatus.StopPending)))
         {
             // Start the service if the current status is stopped.                 
             servicecsv.Start( );               
         }
         else
         {
             // Stop the service if its status is not set to "Stopped".                 
             servicecsv.Stop();
         }  


    }

最佳答案

我以前构建过以类似方式运行的服务,我的建议是不要从外部代码启动和停止服务。相反,应在服务本身内应用计时器方法,该服务应始终运行。在 TimerElapsed 上执行工作,然后返回空闲状态。从而减轻了启动和停止的需要。

此外,如果服务正在“工作”,我会保护服务的“停止”以不允许停止

示例代码

注意:我使用了一个我称之为“归零”的过程与我的计时器。在我的上下文中,归零是让事件在每分钟的零秒触发的过程。为此,我首先将时间设置为每秒触发一次,然后检查当前时间的秒数部分是否为零,一旦出现这种情况,我就会将计时器切换到每分钟。我这样做是为了让自己在测试时保持理智。

此外,我的日程安排是可配置的,所以当它“滴答作响”时,我每分钟都会检查我的配置以查看进程是否“应该”执行。我使用以下 Xml 模式这样做:

    <?xml version="1.0" encoding="utf-8"?>
<ScheduleDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ScheduleInterval>1</ScheduleInterval>
  <ScheduleUnits>min</ScheduleUnits>
  <DailyStartTime>1753-01-01T08:00:00</DailyStartTime>
  <ExcludedWeekDays>
    <string>Sunday</string>
    <string>Saturday</string>
  </ExcludedWeekDays>
  <ExcludedDates>
    <string>12/25</string>
    <string>02/02</string>
    <string>03/17</string>
  </ExcludedDates>
  <DailyRunTimes>
   <!-- code ommitted for size // -->
  </DailyRunTimes>
</ScheduleDefinition>

最后,此代码示例适用于 DataSync 服务,因此对“DataMigrationService”或“DataMigrationManager”的任何引用都是我自己的自定义类,并用作抽象,为我提供一个在服务内控制的对象。

...这是代码:

    using System;
using System.Diagnostics;
using System.Reflection;
using System.ServiceProcess;
using System.Threading;
using System.Xml;
using System.Xml.Serialization;
using DataMigration.Configuration;
using DataMigration.ObjectModel;

namespace DataSyncService
{
    public partial class DataSyncService : ServiceBase
    {
        #region Private Members
        private System.Timers.Timer _timer = null;
        private SimpleScheduleManager.ScheduleDefinition _definition = null;
        private DataMigrationManager _manager = new DataMigrationManager();
        #endregion

        #region Constructor(s)
        public DataSyncService()
        {
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyResolver.Resolve);
            InitializeComponent();
        }
        ~DataSyncService()
        {
            _manager = null;
            _definition = null;
            _timer = null;
        }
        #endregion

        #region Public Method(s)
        protected override void OnStart(string[] args)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            _manager.ProcessMonitor.Logger.Debug("Assembly Version: ", assembly.GetName().FullName);
            assembly = null;

            SetScheduleFromConfigurationFile();

            _timer = new System.Timers.Timer(1000);
            _timer.AutoReset = true;
            _timer.Enabled = true;
            _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_ZeroingProcess);
            _timer.Start();
        }

        protected override void OnStop()
        {
            _timer.Stop();
            _timer.Enabled = false;
            _timer = null;

            // block if the Process is active!
            if (_manager.State == DataMigrationState.Processing)
            {
                // I invented my own CancellableAsyncResult (back in the day), now you can use CancellationTokenSource
                CancellableAsyncResult result = _manager.RequestCancel() as CancellableAsyncResult;
                while (!result.IsCompleted) { Thread.Sleep(ServiceConstants.ThreadSleepCount); }
                try
                {
                    result.EndInvoke();
                }
                catch (Exception ex)
                {
                    ProcessMonitorMessage message = ProcessMonitorMessage.GetErrorOccurredInstance();
                    message.EventType = ProcessMonitorEventType.ProcessAlert;
                    message.Severity = ProcessMessageSeverity.ErrorStop;
                    message.SubjectLine = "Error while stopping service. ";
                    message.EventDescription = ex.Message;

                    _manager.ProcessMonitor.ReportError(message);
                }
            }
        }
        #endregion

        #region Private Method(s)
        private bool MigrationIsScheduledToRunNow()
        {
            DateTime now = DateTime.Now;
            foreach (string dowString in _definition.ExcludedWeekDays)
            {
                if (now.DayOfWeek.ToString().Equals(dowString))
                {
                    Trace.WriteLine("Today is " + dowString, "Excluded by Schedule definition");
                    return false;
                }
            }

            foreach (string datePart in _definition.ExcludedDates)
            {
                string dateString = datePart + "/2008"; // 2008 is a leap year so it "allows" all 366 possible dates.
                DateTime excludedDate = Convert.ToDateTime(dateString);
                if (excludedDate.Day.Equals(now.Day) && excludedDate.Month.Equals(now.Month))
                {
                    Trace.WriteLine("Today is " + datePart, "Excluded by Schedule definition");
                    return false;
                }
            }

            foreach (DateTime runTime in _definition.DailyRunTimes)
            {
                if (runTime.Hour.Equals(now.Hour) && runTime.Minute.Equals(now.Minute))
                {
                    Trace.WriteLine("Confirmed Scheduled RunTime: " + runTime.TimeOfDay.ToString(), "Included by Schedule definition");
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Load Scheduling Configuration Options from the Xml Config file.
        /// </summary>
        private void SetScheduleFromConfigurationFile()
        {
            string basePath = AppDomain.CurrentDomain.BaseDirectory;
            if (basePath.EndsWith("\\")) { basePath = basePath.Substring(0, basePath.Length - 1); }
            string path = string.Format("{0}\\Scheduling\\scheduledefinition.xml", basePath);
            _manager.ProcessMonitor.Logger.Debug("Configuration File Path", path);

            XmlSerializer serializer = new XmlSerializer(typeof(SimpleScheduleManager.ScheduleDefinition));
            XmlTextReader reader = new XmlTextReader(path);
            reader.WhitespaceHandling = WhitespaceHandling.None;
            _definition = serializer.Deserialize(reader) as SimpleScheduleManager.ScheduleDefinition;

            reader = null;
            serializer = null;

        }
        #endregion

        #region Timer Events
        private void _timer_ZeroingProcess(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (DateTime.Now.Second.Equals(0))
            {
                _timer.Interval = 60000;
                _timer.Elapsed -= new System.Timers.ElapsedEventHandler(_timer_ZeroingProcess);
                _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
                _timer_Elapsed(sender, e);
            }
        }

        private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            _manager.ProcessMonitor.Logger.Info("Timer Elapsed", DateTime.Now.ToString());
            if (MigrationIsScheduledToRunNow())
            {
                switch (_manager.State)
                {
                    case DataMigrationState.Idle:
                        _manager.ProcessMonitor.Logger.Info("DataMigration Manager is idle. Begin Processing.");
                        _manager.BeginMigration();
                        break;
                    case DataMigrationState.Failed:
                        _manager.ProcessMonitor.Logger.Warn("Data Migration is in failed state, Email <NotificationRecipients> alerting them.");
                        break;
                    default:
                        _manager.ProcessMonitor.Logger.Warn("DataMigration Manager is still processing.  Skipping this iteration.");
                        break;
                }
            }
        }

        #endregion
    }
}

关于c# - 如何让服务根据服务运行情况动态 Action ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6594626/

相关文章:

javascript - 让 mydesign 填充 asp.net 页面

c# - 使用 ASP.net 核心 web api 发送多个文件

vb.net - 静默运行 CMD

vb.net - VB基于字符串变量从模块中引用属性

c# Get 没有堆栈跟踪的调用方法

c# - 使用 log4net 时直接调用根记录器是一个好习惯吗?

c# - WPF 用户控件,带有按钮和按键绑定(bind)

javascript - 文本框在 javascript 警报后更改高度和边框宽度

vb.net - 如何确定对象是否为VB.NET中的DateTime

c# - Lucene.Net IndexWriter 无法加载文件错误?