【问题标题】:Parallel processing to create PDFs并行处理以创建 PDF
【发布时间】:2015-04-24 12:35:05
【问题描述】:

我想要实现的是使用 iTextSharp 程序集进行多线程生成发票。

在我使用Parallel.ForEach 的理解中,它需要一个 IEnumerable 源并将其委托给不同的线程。

现在我遇到的问题是 1 个进程正在尝试访问另一个进程正在使用的文件。

进程无法访问文件“...\Invoices\INV0000089576PPN.pdf”,因为它正被 另一个进程。

我怎样才能防止这种情况发生?

线程处理

Task task = new Task(() =>
   {
      Parallel.ForEach(orders, currentOrder =>
      {
                LiveTrainingEntities db = new LiveTrainingEntities();
                var trans = db.Transactions.SingleOrDefault(x => x.fTransactionID == currentOrder.TransactionID);

                if (trans != null)
                {
                    var labOrderInvoices = GetLabOrderInvoices(trans.Practices.fPracticeID, currentOrder.TaxInvoiceNumber);
                    CreateLabOrderInvoice(PopulateHTML(labOrderInvoices), currentOrder.TaxInvoiceNumber);

                    Console.WriteLine("Processing {0} on thread {1}", currentOrder.TaxInvoiceNumber,
                                Thread.CurrentThread.ManagedThreadId);

                    //orders.Remove(currentOrder);
       }
   });
});
task.Start();
task.Wait();

PDF方法

static void CreateLabOrderInvoice(string html, string invoiceNumber)
    {
        try
        {
            string strHtml = null;
            MemoryStream memStream = new MemoryStream();

            strHtml = html;

            string strFileShortName = invoiceNumber + ".pdf";
            string strFileName = @"~\Invoices\" + strFileShortName;
            iTextSharp.text.Document docWorkingDocument = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4, 40, 40, 40, 40);
            StringReader srdDocToString = null;

            try
            {
                PdfWriter pdfWrite = default(PdfWriter);

                pdfWrite = PdfWriter.GetInstance(docWorkingDocument, new FileStream(strFileName, FileMode.Create));
                srdDocToString = new StringReader(strHtml);

                docWorkingDocument.Open();

                Image logo = Image.GetInstance(@"~\images\Image_PPNLOGO.jpg");
                logo.Alignment = Image.ALIGN_RIGHT;

                docWorkingDocument.AddTitle("Lab Order Invoice");
                docWorkingDocument.Add(logo);

                XMLWorkerHelper.GetInstance().ParseXHtml(pdfWrite, docWorkingDocument, srdDocToString);
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
            finally
            {
                if ((docWorkingDocument != null))
                {
                    docWorkingDocument.Close();
                }
                if ((srdDocToString != null))
                {
                    srdDocToString.Close();
                    srdDocToString.Dispose();
                }
            }
        }
        catch (System.Exception ex)
        {
            throw ex;
        }


    }

编辑 这是堆栈跟踪

在 ConsoleApplication1.Program.CreateLabOrderInvoice(String html, 字符串 invoiceNumber) 在 ~\Program.cs:line 416 at ConsoleApplication1.Program.c__DisplayClass4.b__3(order currentOrder) 在 ~\Program.cs:line 70 at System.Threading.Tasks.Parallel.c__DisplayClass2d2.<ForEachWorker>b__23(Int32 i) at System.Threading.Tasks.Parallel.<>c__DisplayClassf1.b__c()

【问题讨论】:

  • 谁在使用该 pdf?它是并行循环中的另一个线程吗?
  • 不要这样做throw ex;,如果这样做,您将丢失堆栈跟踪。要么做throw;,要么根本没有catch,你可以有一个try,有一个finally,没有catch
  • @SriramSakthivel,是的,我认为这可能是另一个可能导致问题的线程
  • 如果是这样,你为什么还要在两个线程中访问它?为什么会有碰撞? invoiceNumber 在列表中不是唯一的吗?
  • @YuvalItzchakov PdfWriter 在他的代码中暗示他写了:)

标签: c# multithreading pdf itextsharp


【解决方案1】:

您的问题是您通过使用 currentOrder.TaxInvoiceNumber 字段的值作为唯一的唯一鉴别符,为 PDF 生成一个文件名,您认为该文件名对于特定订单是唯一的。

但是,从您得到的错误中可以清楚地看出,它并不像您想象的那么独特,并且似乎某些订单对该字段具有相同的值。

您的选择:

  1. 不仅可以按订单,还可以按订单/税务发票号码组合对数据进行分区。
  2. 使用两个 ID 的组合(即订单 ID + 税务发票号)生成文件名
  3. 使用连续的 ID + 税务发票号作为文件名,以确保它是唯一的。

【讨论】:

  • 如果是这样,我建议您记录 Console.WriteLine("Processing {0} on thread {1}", currentOrder.TaxInvoiceNumber, Thread.CurrentThread.ManagedThreadId);在 CreateLabOrderInvoice 调用之前。当您在输出中收到错误时,您可能会看到重复的发票
  • 与文件名的唯一性无关。正是线程试图访问导致该问题的相同文件名。我需要一种方法来防止这种情况发生
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-05
  • 1970-01-01
  • 2019-07-30
  • 2018-02-09
  • 1970-01-01
  • 2015-07-16
相关资源
最近更新 更多