C# 如何使服务根据服务运行情况动态地动作

C# 如何使服务根据服务运行情况动态地动作,c#,asp.net,vb.net,C#,Asp.net,Vb.net,嗨,朋友们,我正试图让我的服务动态运行。。。我已经为我的服务设置了大约2分钟的时间,如果假设它正在做大量的工作意味着它将超过2分钟的时间限制,那么我们需要检查服务条件,如果工作正在等待,意味着我们需要运行该实例直到完成 所以我在谷歌上尝试了下面的代码。。。我有办法在下面的服务中我需要合作,有人能帮我吗 public static void StartService(string serviceName, int timeoutMilliseconds) { ServiceContro

嗨,朋友们,我正试图让我的服务动态运行。。。我已经为我的服务设置了大约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();
         }  


    }

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

此外,我将保护服务的“停止”,以防在服务“工作”时停止服务

示例代码

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

此外,我的日程安排是可配置的,所以每分钟当它“滴答”一声时,我都会检查我的配置,看看流程是否“应该”执行。我使用以下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>

1.
闵
1753-01-01T08:00:00
星期日
星期六
12/25
02/02
03/17
最后,此代码示例是针对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
    }
}
使用系统;
使用系统诊断;
运用系统反思;
使用System.ServiceProcess;
使用系统线程;
使用System.Xml;
使用System.Xml.Serialization;
使用DataMigration.Configuration;
使用DataMigration.ObjectModel;
命名空间数据同步服务
{
公共部分类DataSyncService:ServiceBase
{
#区域私人成员
private System.Timers.Timer _Timer=null;
私有SimpleScheduleManager.ScheduleDefinition_definition=null;
私有数据迁移管理器_manager=new DataMigrationManager();
#端区
#区域构造函数
公共数据同步服务()
{
AppDomain.CurrentDomain.AssemblyResolve+=新的ResolveEventHandler(AssemblyResolver.Resolve);
初始化组件();
}
~DataSyncService()
{
_manager=null;
_定义=空;
_定时器=空;
}
#端区
#区域公共方法
启动时受保护的覆盖无效(字符串[]args)
{
Assembly=Assembly.getExecutionGassembly();
_manager.ProcessMonitor.Logger.Debug(“程序集版本:”,Assembly.GetName().FullName);
assembly=null;
SetScheduleFromConfigurationFile();
_定时器=新系统定时器定时器定时器(1000);
_timer.AutoReset=true;
_timer.Enabled=true;
_timer.appead+=新系统.Timers.ElapsedEventHandler(_timer_zeroningprocess);
_timer.Start();
}
受保护的覆盖void OnStop()
{
_timer.Stop();
_timer.Enabled=false;
_定时器=空;
//如果进程处于活动状态,请阻止!
if(_manager.State==DataMigrationState.Processing)
{
//我发明了我自己的CancelableAsyncResult(回到当年),现在您可以使用CancellationTokenSource
CancelableAsyncResult=\u manager.RequestCancel()作为CancelableAsyncResult;
而(!result.IsCompleted){Thread.Sleep(ServiceConstants.ThreadSleepCount);}
尝试
{
result.EndInvoke();
}
捕获(例外情况除外)
{
ProcessMonitorMessage=ProcessMonitorMessage.GetErrorOccurrendInstance();
message.EventType=ProcessMonitorEventType.ProcessAlert;
message.Severity=ProcessMessageSeverity.ErrorStop;
message.SubjectLine=“停止服务时出错。”;
message.EventDescription=ex.message;
_manager.ProcessMonitor.ReportError(消息);
}
}
}
#端区
#区域专用方法
private bool MigrationScheduledToRunnow()
{
DateTime now=DateTime.now;
foreach(字符串dowString在_定义中。不包括工作日)
{
if(now.DayOfWeek.ToString().Equals(dowString))
{
Trace.WriteLine(“今天是“+dowString”,不包括在附表定义中”);
返回false;
}
}
foreach(字符串datePart在_定义中。排除数据项)
{
string dateString=datePart+“/2008”;//2008是闰年,所以它“允许”所有366个可能的日期。
DateTime excludedDate=Convert.ToDateTime(日期字符串);
if(excludedDate.Day.Equals(now.Day)&&excludedDate.Month.Equals(now.Month))
{
Trace.WriteLine(“今天是“+日期部分”,不包括在附表定义中”);
返回false;
}
}
foreach(在_definition.dailRuntimes中的日期时间运行时)
{
如果(runTime.Hour.Equals)(now.Hour