2017-01-04 2 views
2

Dans mon application Web, j'utilise wkhtmltopdf pour traiter les rapports afin de les afficher au format PDF. J'ai quelques fonctions qui compilent du code HTML ensemble, des en-têtes, etc., puis transmettent cette information à wkhtmltopdf pour compiler le PDF et le servir à l'utilisateur.Le verrouillage des fonctions et l'utilisation de Mutex se comportent différemment dans IIS Express et IIS

Quelque chose comme:

public JsonResult BuildPDF(string one, string two, SomeData[] data, SomeList[] { 
lock(PDFLock) { 
     // ... Code here to compile HTML and save to files 

     ProcessStartInfo psi = new ProcessStartInfo(); 
     psi.FileName = @"C:\inetpub\wwwroot\MySite\wkhtmltopdf.exe"; 
     psi.UseShellExecute = true; 
     psi.Verb = "runas"; 
     ... 
     Process p = Process.Start(psi); 
     p.WaitForExit(); 
    } 
} 

Une fois le PDF est compilé je pousse à l'utilisateur puis supprimez le fichier.

Comme vous pouvez le voir, j'ai un verrou autour de cette fonction pour éviter deux tentatives de traitement d'un PDF à la fois. Sur IIS Express cette fonction se comporte comme je m'y attendrais: si deux demandes sont faites exactement au même moment, la requête qui le fait en premier sera traitée, et la deuxième requête s'asseoira et attendra sur le verrou jusqu'à ce que la première demande soit complète .

Dans la version IIS, il semble ignorer ce verrou, et n'attend pas la fin de la première demande. Il finit par sauter la fonction si rapidement que la première demande est en cours d'exécution tandis que la deuxième demande se termine (sans succès), de sorte que l'utilisateur reçoit un message indiquant que la demande a échoué.

Je ne suis pas sûr pourquoi il ignorerait ce verrou, ou pourquoi il fonctionnerait dans le débogage (IIS Express).

Y a-t-il une possibilité que cela soit dû à la configuration d'IIS?

Edit:

Le problème avec lock était un problème de processus de travail dans IIS. Je suis en train de tester Mutex maintenant avec plusieurs processus.

Edit:

utilisation Mutex: le Mutex est déclaré dans la classe comme private static Mutex mut = new Mutex();

public JsonResult BuildPDF(string one, string two, SomeData[] data, SomeList[] { 
     mut.WaitOne(); 
     // ... Code here to compile HTML and save to files 

     ProcessStartInfo psi = new ProcessStartInfo(); 
     psi.FileName = @"C:\inetpub\wwwroot\MySite\wkhtmltopdf.exe"; 
     psi.UseShellExecute = true; 
     psi.Verb = "runas"; 
     ... 
     Process p = Process.Start(psi); 
     p.WaitForExit(); 

    //... Return some JSON to user 
    } 

Puis dans la méthode Download:

public virtual void Download() { 
// ... Response headers and stuff 
    Response.TransmitFile(@"C:\inetpub\wwwroot\MySite\temppdfs\pdfout.pdf"); 
    Response.End();      

    System.IO.File.Delete(@"C:\inetpub\wwwroot\MySite\temppdfs\pdfout.pdf"); 
    mut.ReleaseMutex(); 
} 
+0

Ma compréhension est que 'Process.Start' ne bloquera pas le thread courant (c'est-à-dire que l'exécution continuera après le démarrage du processus). Si cela est vrai, votre verrou sera libéré pendant que votre processus est en cours d'exécution. – AndySavage

+0

Hmm peut-être que c'est le cas, mais je ne sais pas pourquoi cela fonctionne correctement dans IIS Express alors: S – sosil

+0

Je devrais également noter que j'ai p.WaitForExit(), que j'espérais bloquer jusqu'à ce que le processus est sorti – sosil

Répondre

1

Ma compréhension était un peu hors de lock et Mutex utilisation.

La raison lock ne fonctionnait pas est que mon pool d'applications dans IIS avait plusieurs processus de travail autorisés (4), donc le verrou ne pouvait pas fonctionner de processus croisés.

j'utilisais le Mutex mal en le déclarant en dehors des fonctions, maintenant l'utilisation correcte de Mutex dans mon cas (version IIS avec plusieurs processus dans le pool d'applications):

public JsonResult BuildPDF(string one, string two, SomeData[] data, SomeList[] { 
    Mutex mut = new Mutex(false, @"Global\PDFMutex"); 
    mut.WaitOne(); 

    // ... Code here to compile HTML and save to files 

    ProcessStartInfo psi = new ProcessStartInfo(); 
    psi.FileName = @"C:\inetpub\wwwroot\MySite\wkhtmltopdf.exe"; 
    psi.UseShellExecute = true; 
    psi.Verb = "runas"; 
    ... 
    Process p = Process.Start(psi); 
    p.WaitForExit(); 

    mut.ReleaseMutex(); 

//... Return some JSON to user 
} 

Cette utilisation de Mutex apparaît réussir avec plusieurs processus et plusieurs fonctions.