IIS Express 和 IIS 中功能锁和互斥量的使用行为不同

Function lock and Mutex usage behaving differently in IIS Express and IIS

在我的 Web 应用程序中,我使用 wkhtmltopdf 处理报告以将其输出为 PDF。我有一些函数可以将一些 HTML 编译在一起,一些 headers 等,然后将此信息传递给 wkhtmltopdf 以编译 PDF 并将其提供给用户。

类似于:

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();
    }
}

编译 PDF 后,我将其推送给用户,然后删除文件。

如您所见,我对该函数进行了锁定,以防止两次尝试同时处理一个 PDF。 IIS Express 上,此函数的行为符合我的预期:如果同时发出两个请求,则第一个发出请求的请求将被处理,第二个请求将等待锁定直到第一个请求完成。

在发布的 IIS 中,它似乎忽略了这个锁,并且不等待第一个请求完成。它实际上最终跳过了这个函数,以至于第一个请求 still 运行 而第二个请求完成(不成功),所以用户收到一条请求失败的消息.

我不确定为什么它会忽略这个锁,或者为什么它会在调试 (IIS Express) 中工作。

这是否可能是 IIS 配置的问题?

编辑:

lock 的问题是 IIS 中多个工作进程的问题。我现在正在使用多个进程再次测试 Mutex。

编辑:

Mutex 用法:Mutex 在 class 中声明为 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
    }

然后在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();
}

我对 lockMutex 用法的理解有点偏差。

lock 不工作的原因是我在 IIS 中的应用程序池允许多个工作进程 (4),因此锁无法跨进程工作。

我在函数外声明 Mutex 时使用不当,现在 Mutex 在我的例子中的正确用法(在应用程序池中发布带有多个进程的 IIS):

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
}

Mutex 的这种用法在多个进程和多个函数中似乎是成功的。