CustomValidationAttribute nie je thread-safe

Nedávno som narazil na chybičku v CustomValidationAttribute. A to konkrétne, že inicializačná procedúra v tejto triede nie je thread-safe. Presnejšie na začiatku tejto procedúry sa nastaví flag, že inicializácia už prebehla. Avšak ak medzitým nejaký iný thread validuje inú inštanciu tej istej triedy, tak si myslí že inicializácia už prebehla a pri spustení validačnej metódy vznikne NullReferenceException. A presne toto sa stalo mne.

Tento scenár sa vám asi ťažko podarí spraviť v nejakej webovej aplikácii. To by muselo niekoľko užívateľov naraz uložiť záznam rovnakého typu a aj to po spustení aplikácie. Ak sa to totiž raz podarí, tak atribút zostane inicializovaný až do ukončenia aplikácie.

Preto mne sa podarilo na túto chybu naraziť až keď som robil job, ktorý synchronizuje dáta v aplikácii. A aby to bežalo rýchlejšie, tak každý záznam sa synchronizuje paralelne cez Parallel.ForEach. A práve tu už nebol problém naraziť na NullReferenceException.

Bližší popis chyby je na connecte: http://connect.microsoft.com/VisualStudio/feedback/details/675788/customvalidationattribute-is-not-thread-safe

Nájdete tu aj zdrojový kód programu, ktorý presne túto chybu simuluje.

Komentáre

# liero said:

hmm, o toto sa nestara samotny .NET? teda ze kym nezbehne staticky konstruktor, tak nieje mozne vytvorit instanciu objektu a to ani v inom threade?

Wednesday, June 29, 2011 4:07 PM
# duracellko said:

to je sice pravda, ale v tomto pripad nejde o staticku inicializaciu. Initializacia spociva v tom, ze sa musi najst MethodInfo podla nazvu metody. A toto sa robi on demand, cize az ked sa spusti validacia.

Pokial by sa to robilo v konstruktore, tak je vsetko v poriadku, lebo konstruktor atributu sa vola spolu s nahranim typu a to sa synchronizuje, aby sa dany typ nahral a skompiloval len raz.

Zase je mozne, ze ak by sa MethodInfo vyhladavala uz v konstruktore, tak by sa nahravanie typu mohlo za urcitych okolnosti zacyklit. Ale tym som si nie isty.

Wednesday, June 29, 2011 5:35 PM
Prihlásiť | Registrovať | Pomoc