Ich habe eine Problemeinheit, die eine Klasse testet, die Ereignisse auslöst, wenn ein Thread startet und endet. Eine abgespeckte Version der Quelle ist wie folgt:
%Vor% Ich habe dann einen Test, um zu überprüfen, ob das Finished
-Ereignis ausgelöst wird, nachdem% code_% wie folgt beendet wurde:
Die Idee ist also, dass der Test für maximal eine Sekunde blockiert - oder bis das LongRunningMethod
-Ereignis ausgelöst wird - bevor überprüft wird, ob das Finish
-Flag gesetzt ist.
Natürlich habe ich etwas falsch gemacht, da manchmal der Test bestanden wird, manchmal nicht. Das Debuggen scheint sehr schwierig zu sein, und die Breakpoints, die ich erwarten würde (z. B. die Methode finished
), scheinen nicht immer zu sein.
Ich gehe davon aus, dass dies nur mein Missverständnis ist, wie Threading funktioniert, also hoffentlich kann mich jemand aufklären.
Eine Sperre ist hier nicht angebracht, Sie möchten ein Ereignis signalisieren. Zum Beispiel:
%Vor%Vlad hat absolut recht, aber ich werde noch einmal versuchen, das Problem zu klären:
%Vor% Sie können es mit einem Warte-Handle einer Art tun. Ich würde ein ManualResetEvent
verwenden:
Ich habe kürzlich eine Reihe von Blogposts zu Unit-Testing-Ereignissequenzen für Objekte geschrieben, die sowohl synchrone als auch asynchrone Ereignisse veröffentlichen. Die Posts beschreiben einen Einheitentestansatz und ein Framework und liefern den vollständigen Quellcode mit Tests.
Die Verwendung der Framework-Tests kann folgendermaßen aussehen:
%Vor%Der EventMonitor führt alle schweren Aufgaben durch und führt den Test (Aktion) aus und bestätigt, dass Ereignisse in der erwarteten Reihenfolge ausgelöst werden (expectedSequence). Es verarbeitet asynchrone Ereignisse und gibt bei Fehlern beim Test eine gute Diagnose aus.
Es gibt eine Menge Details in den Beiträgen, in denen die Probleme und Ansätze sowie der Quellcode beschrieben werden:
Sie testen scheint falsch zu sein. Angenommen, dass nach threadTest.FinishThreadTest();
lock durch den Code in CheckFinishedEventFiresTest()
erhalten wird. Dann wird der Test fehlschlagen. Du hast hier eine klare Race Condition.
Beachten Sie, dass die Rückgabe von FinishThreadTest()
nicht garantiert, dass der Thread fertig ist. Es setzt nur die Flagge für den Thread, die zu jedem Zeitpunkt berücksichtigt werden kann (nichts garantiert grundsätzlich, dass der Thread sofort vom Scheduler ausgeführt wird).
In Ihrem Fall wird der Thread höchstwahrscheinlich mit Sleep()
ing beschäftigt sein. Nach dem Aufruf von threadTest.FinishThreadTest();
wird die Sperre höchstwahrscheinlich von dem Thread übernommen, in dem CheckFinishedEventFiresTest()
ausgeführt wird. Der Monitor wartet 1 Sekunde und gibt dann auf. Danach wird die Sperre aufgehoben, sodass der Delegierte nur in diesem Moment sperren kann.
Tags und Links .net c# unit-testing multithreading thread-safety