C#中的计时器和处理问题

时间:2017-08-18 15:18:25

标签: c# service timer

我有一个处理文件的服务。有时它们处理得非常快,有时它们需要很长时间。我无法控制将文件发送给我的过程。在白天和晚上随机掉落在我身上。当我使用计时器时,它似乎是" ProcessFiles"当时间结束并且再次调用ProcessFiles时,方法被放弃。由于文件包含敏感信息,因此他们无法长时间坐在服务器上,因此我无法将计时器设置为超过5分钟,并且仍然在5分钟时,该过程有时会中断自身。结果,我有部分处理过的文件。我很感激任何有关这一困境的想法和意见。

    System.Timers.Timer _timer;

    // As the files come in, massage them and encrypt them

    public const string InPath = @"c:\input";
    public const string OutPath = @"\c:\output";

    public FileMassaging()
    {
        InitializeComponent();
    }

    public EventLog MyEventLog = new EventLog();
    public string sSource = "FileMassaging";
    public string sLog = "FileMassaging";

    protected override void OnStart(string[] args)
    {
        // Create the source, if it does not already exist.
        if (!EventLog.SourceExists(sSource))
            EventLog.CreateEventSource(sSource, sLog);

        // set up the service
        ServiceStatus serviceStatus = new ServiceStatus();
        serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING;
        serviceStatus.dwWaitHint = 100000;
        SetServiceStatus(this.ServiceHandle, ref serviceStatus);

        // set up the service

        _timer = new System.Timers.Timer();
        _timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
        _timer.Interval = 5000;
        _timer.Start();


        // Update the service state to Running.
        serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
        SetServiceStatus(this.ServiceHandle, ref serviceStatus);
    }


    public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
    {
        ProcessFiles();
    }


      public void ProcessFiles()
    {
            string[] originalFiles = Directory.GetFiles(InPath + @"\", "*.txt");
            foreach (string fileName in originalFiles)
            {
                 // Check and process the file
                 CheckFile(InPath, OutPath, fileName);
            } 

    }

    public void CheckFile(string InPath,Outpath, fileName)

      {
       // for example only -- actual file processing is much longer
       // 
       string infile = InPath+fileName;
       string outfile= OutPath+fileName;
       File.Move(infile,outfile,true);
      }

2 个答案:

答案 0 :(得分:1)

从定时器上的MSDN页面尝试此操作(https://msdn.microsoft.com/en-us/library/system.timers.timer.interval(v=vs.110).aspx

_timer = new System.Timers.Timer(5);
_timer.Elapsed += OnTimer;
_timer.AutoReset = true;
// _timer.Start();
_timer.Enable = true;

private static void OnTimer(object sender, System.Timers.ElapsedEventArgs args) { ProcessFiles(); }

答案 1 :(得分:1)

对于测试和可扩展性,我建议使用不同的整体结构。

首先让我们将这项工作分成有意义的课程。让我们从一个名为FolderWatcher的类开始:

public class FolderWatcher
    {
        private readonly string _inPath;
        private readonly string _outPath;

        public bool CurrentlyRunning { get; set; }

        public FolderWatcher(string inPath, string outPath)
        {
            _inPath = inPath;
            _outPath = outPath;
        }

        public void TryProcessFiles(object sender, ElapsedEventArgs e)
        {
            try
            {
                this.CurrentlyRunning = true;
                ProcessFiles(sender, e);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                this.CurrentlyRunning = false;
            }
        }

        public void ProcessFiles(object sender, ElapsedEventArgs e)
        {

            string[] originalFiles = GetFilesInDirectory();
            foreach (var originalFile in originalFiles)
            {
                CheckFile(originalFile);
            }
        }

        // Internal/Virtual so that this can mocked in unit testing.
        internal virtual string[] GetFilesInDirectory()
        {
            return Directory.GetFiles(_inPath + @"\", "*.txt");
        }

        // Internal/Virtual so that this can mocked in unit testing.
        internal virtual void CheckFile(string fileName)
        {
            string infile = $"{_inPath}{fileName}";
            string outfile = $"{_outPath}{fileName}";
            File.Move(infile, outfile);
        }

    }

此类只负责移动文件以响应事件。

接下来让我们构建一个类来包装处理计时器功能的FolderWatcher类:

    public class TimedFolderWatcher
    {
        private readonly FolderWatcher _folderWatcher;
        private readonly Timer _timer;

        public TimedFolderWatcher(FolderWatcher folderWatcher)
        {
            _folderWatcher = folderWatcher;
            InitTimer();
        }

        private void InitTimer()
        {
            _timer.Elapsed += new System.Timers.ElapsedEventHandler(this.ProcessFiles);
            _timer.Interval = 5000;
            _timer.Start();
        }

        private void ProcessFiles(object sender, ElapsedEventArgs e)
        {
            _folderWatcher.TryProcessFiles(sender, e);
        }
    }

这个类也有责任每5000毫秒调用一次ProcessFiles方法。

最后,我们可以通过这种方式初始化并调用这些类:

var fileMassageService = new TimedFolderWatcher(new FolderWatcher(@"c:\input", @"c:\output"));

这种方法有助于测试并遵循依赖注入的最佳实践,如果需要,将来可以使用IOC框架。