Help with synchronization from a unit test in C# -
i'm testing class wraps backgroundworker perform operation away ui thread in application.
the test below fails if timeout exceeded , passes if progresseventcount reaches expected number of events before then.
my question synchronization. asyncexecutor.progressed fired thread pool thread backgroundworker using , test thread reads in while loop.
am using lock correctly?
[test] [timeout(1250)] public void execute() { var locker = new object(); const int numberofevents = 10; const int frequencyofevents = 100; var start = datetime.now; int progresseventcount = 0; igradualoperation tester = new testgradualoperation(numberofevents, frequencyofevents); var asyncexecutor = new asynchronousoperationexecutor(); asyncexecutor.progressed += (s, e) => { lock (locker) progresseventcount++; }; asyncexecutor.execute(tester); while (true) { int count; lock (locker) { count = progresseventcount; } if (count < numberofevents) continue; assert.pass("succeeded after {0} milliseconds", (datetime.now - start).totalmilliseconds); } } // implementation public class asynchronousoperationexecutor { public void execute(igradualoperation gradualoperation) { var backgroundworker = new backgroundworker {workerreportsprogress = true}; backgroundworker.dowork += backgroundworkerdowork; backgroundworker.progresschanged += backgroundworkerprogresschanged; backgroundworker.runworkerasync(gradualoperation); } private void backgroundworkerprogresschanged(object sender, progresschangedeventargs e) { var myargs = e.userstate progresseventargs; onprogressed(myargs); } static void backgroundworkerdowork(object sender, doworkeventargs e) { var workerthis = sender backgroundworker; var operation = e.argument igradualoperation; if (workerthis == null || operation == null) return; operation.progressed += (s, e1) => workerthis.reportprogress((int)e1.percentage, e1); operation.run(); } private void onprogressed(progresseventargs e) { if (progressed != null) progressed(this, e); } public event eventhandler<progresseventargs> progressed; } // test helper class public class testgradualoperation : igradualoperation { private readonly int _numberofevents; private readonly int _frequencymilliseconds; public testgradualoperation(int numberofevents, int frequencymilliseconds) { _numberofevents = numberofevents; _frequencymilliseconds = frequencymilliseconds; } public void run() { (int = 0; < _numberofevents; i++) { thread.sleep(_frequencymilliseconds); onprogressed(new progresseventargs(i, _numberofevents)); } } private void onprogressed(progresseventargs e) { if (progressed != null) progressed(this, e); } public event eventhandler<progresseventargs> progressed; }
i think revision improvement, blocking test thread , signalling autoresetevent. not winning brownie points test readability though.
[test] [timeout(1250)] public void execute() { var locker = new object(); eventwaithandle waithandle = new autoresetevent(false);// <-- const int numberofevents = 10; const int frequencyofevents = 100; var start = datetime.now; int progresseventcount = 0; igradualoperation tester = new testgradualoperation(numberofevents, frequencyofevents); var asyncexecutor = new asynchronousoperationexecutor(); asyncexecutor.progressed += (s, e) => { lock (locker) { progresseventcount++; waithandle.set();// <-- } }; asyncexecutor.execute(tester); while (true) { waithandle.waitone();// <-- if (progresseventcount < numberofevents) continue; assert.pass("succeeded after {0} milliseconds", (datetime.now - start).totalmilliseconds); } }
Comments
Post a Comment