explication que je peux Simplest produire:verrouillage utilisé dans le rappel du cache d'objet et une autre méthode ne semble pas verrouiller
Dans mon application web .NET1.1 créer un fichier sur le disque, dans la méthode de rendu, et ajouter un élément dans le cache expirant dans, disons, une minute. J'ai aussi une méthode de rappel, à appeler quand l'élément de cache expire, qui supprime le fichier créé par Render. Dans la méthode Page_Init, j'essaie d'accéder au fichier que la méthode Render a écrite sur le disque. Ces deux méthodes ont une instruction lock, verrouillant un objet statique privé.
Intention:
Pour créer une page qui écrit essentiellement une copie de lui-même sur le disque, ce qui est supprimé avant qu'il ne soit trop vieux (ou hors de ce jour, sage contenu), tout en servant le fichier si elle existe sur le disque.
problème observé:
C'est vraiment deux questions, je pense. Demander la page fait ce que j'attends, elle restitue la page sur le disque et la sert immédiatement, tout en ajoutant l'élément d'expiration au cache. Pour tester le temps d'expiration est de 1 minute.
Je m'attends alors à ce que la méthode de rappel soit appelée après 60 secondes et efface le fichier. Ce n'est pas le cas. Après une autre minute (par souci d'argument), je rafraîchis la page dans le navigateur. Ensuite, je peux voir la méthode de rappel s'appeler et placer un verrou sur l'objet de verrouillage. Le Page_Init est également appelé et place un verrou sur le même objet. Cependant, les deux méthodes semblent entrer leur bloc de code de verrouillage et poursuivre l'exécution. Résultat: Le fichier de vérification de rendu est présent, la méthode de rappel supprime le fichier, la méthode de rendu essaie de servir le fichier maintenant supprimé.
extrait de code Horriblement simplifié:
public class MyPage : Page
{
private static Object lockObject = new Obect();
protected void Page_Init(...)
{
if (File.Exists(...))
{
lock (lockObject)
{
if (File.Exists(...))
{
Server.Transfer(...);
}
}
}
}
protected override void Render(...)
{
If (!File.Exists(...))
{
// write file out and serve initial copy from memory
Cache.Add(..., new CacheItemRemovedCallback(DoCacheItemRemovedCallback));
}
}
private static void DoCacheItemRemovedCallback(...)
{
lock (lockObject)
{
If (File.Exists(...))
File.Delete(...);
}
}
}
Quelqu'un peut-il expliquer cela, s'il vous plaît? Je comprends que la méthode de rappel est, paresseusement, paresseuse et donc ne rappelle que lorsque je fais une demande, mais sûrement le thread dans .NET1.1 est assez bon pour ne pas laisser deux blocs lock() entrer simultanément?
Merci,
Matt.
Non connexe, mais: 'private static Object lockObject = new Obect()' - sur une page Web? Cela signifie que * toutes * les demandes partagent un verrou - est-ce ce que vous vouliez? –
Peut-être que je ne comprends pas cela correctement, mais il semble que vous dupliquiez la fonctionnalité de la directive OutputCache? Voir http://msdn.microsoft.com/en-us/library/hdxfb6cy(VS.71).aspx – PhilPursglove
[Silence embarrassant] Oui, il semblerait que oui. En fait, j'avais l'impression que .NET1.1 n'était pas disponible. Je vais maintenant me casser la tête et essayer de me rappeler pourquoi et si cela impliquait une faille dans le 1.1 OutputCache. Ensuite, je vais l'utiliser. Merci. [Plus de silence] –