【问题标题】:Timer and Processing Issues in C#C# 中的计时器和处理问题
【发布时间】:2017-08-18 15:18:24
【问题描述】:

我有一个处理文件的服务。有时他们处理得非常快,有时他们需要很长时间。我无法控制将文件发送给我的过程。白天和晚上随机掉落在我身上。当我使用计时器时,似乎“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);
      }

【问题讨论】:

  • 我想我不明白定时器的要求。为什么不只使用文件夹观察程序,并在创建文件时执行您需要执行的操作,然后移动文件。或者控制将文件放在那里进行加密的过程?
  • 我想我看到的最好的方式是为什么等待计时器,在进入时移动。再说一次,如果你要搬家,为什么不把它放在你搬家的地方呢。
  • 我将编辑我的问题,但来自其他地方的文件会随机放入我们的文件夹中,我们必须对其进行按摩和加密。文件监视器不够可靠。如果同时出现一堆文件,它不会以我可以处理所有文件的方式提醒我,因此文件会丢失。
  • 关于this deleted question,如果您删除该问题,任何人都无法发表评论,以帮助您改进或提供更多详细信息。

标签: c# service timer


【解决方案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 框架。

【讨论】:

  • 谢谢。我会详细研究一下,看看我能不能完成这项工作。
  • 嗨 P Roe - 感谢您的周到 cmet。这是一个更好的方法。我是否仍然不会遇到服务在 CheckFiles 方法中间停止并直接转到 _folderWatcher.ProcessFiles 的问题?
  • 我的问题原来是代码中存在错误并且服务忽略了它。在按照您的建议重组我的代码后,我能够找到它,因此我将其标记为已回答。非常感谢您的帮助!
【解决方案2】:

从 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(); }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-10
    • 1970-01-01
    • 2019-07-12
    • 2015-08-23
    • 1970-01-01
    • 1970-01-01
    • 2020-05-16
    相关资源
    最近更新 更多