service - Timer and Processing Issues in C# -
i have service processes files. process , take long time. can't control process sends files me. randomly dropped on me throughout day , night. when use timer, seems "processfiles" method abandoned whereever when time has elapsed , processfiles called again. since files contain sensitive information, can't sit on server long time can't set timer longer 5 minutes and, still, @ 5 minutes, process interrupts itself. result, have partially processed files. appreciate thoughts , input on quandary.
system.timers.timer _timer; // files come in, massage them , 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 source, if not exist. if (!eventlog.sourceexists(ssource)) eventlog.createeventsource(ssource, slog); // set service servicestatus servicestatus = new servicestatus(); servicestatus.dwcurrentstate = servicestate.service_start_pending; servicestatus.dwwaithint = 100000; setservicestatus(this.servicehandle, ref servicestatus); // set service _timer = new system.timers.timer(); _timer.elapsed += new system.timers.elapsedeventhandler(this.ontimer); _timer.interval = 5000; _timer.start(); // update service state 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 , process file checkfile(inpath, outpath, filename); } } public void checkfile(string inpath,outpath, filename) { // example -- actual file processing longer // string infile = inpath+filename; string outfile= outpath+filename; file.move(infile,outfile,true); }
for testing , extensiblity recommend different overall structure.
first let's seperate out work classes makes sense. lets start class called 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; } { this.currentlyrunning = false; } } public void processfiles(object sender, elapsedeventargs e) { string[] originalfiles = getfilesindirectory(); foreach (var originalfile in originalfiles) { checkfile(originalfile); } } // internal/virtual can mocked in unit testing. internal virtual string[] getfilesindirectory() { return directory.getfiles(_inpath + @"\", "*.txt"); } // internal/virtual can mocked in unit testing. internal virtual void checkfile(string filename) { string infile = $"{_inpath}{filename}"; string outfile = $"{_outpath}{filename}"; file.move(infile, outfile); } }
this class has single responsibility, move files in response event.
next let's build class wrap folderwatcher class handles timer functionality:
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); } }
this class has single responsibility call processfiles method every 5000 milliseconds.
lastly can init , call these classes way:
var filemassageservice = new timedfolderwatcher(new folderwatcher(@"c:\input", @"c:\output"));
this approach lends testing , follows best practices of dependency injection allow use ioc framework in future if need to.
Comments
Post a Comment