PDFsharp & MigraDoc Foundation
https://forum.pdfsharp.net/

Is PdfDocumentRenderer thread safe?
https://forum.pdfsharp.net/viewtopic.php?f=2&t=3674
Page 1 of 1

Author:  vorobej [ Fri Oct 13, 2017 5:09 pm ]
Post subject:  Is PdfDocumentRenderer thread safe?

I've tried to run this code multithreaded, each receiving its own copy of pdfDoc, but getting the exception below. Is it me or the class is not thread safe?

Code:
PdfDocumentRenderer renderer = new PdfDocumentRenderer(true);
renderer.Document = pdfDoc;
renderer.RenderDocument(); // exception thrown here


Code:
System.ArgumentException occurred
  HResult=0x80070057
  Message=An item with the same key has already been added.
  Source=mscorlib
  StackTrace:
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at PdfSharp.Fonts.OpenType.GlyphTypefaceCache.AddGlyphTypeface(XGlyphTypeface glyphTypeface)
   at PdfSharp.Drawing.XGlyphTypeface.GetOrCreateFrom(String familyName, FontResolvingOptions fontResolvingOptions)
   at PdfSharp.Drawing.XFont.Initialize()
   at PdfSharp.Drawing.XFont..ctor(String familyName, Double emSize, XFontStyle style, XPdfFontOptions pdfOptions)
   at MigraDoc.Rendering.FontHandler.FontToXFont(Font font, PdfFontEncoding encoding)
   at MigraDoc.Rendering.ParagraphRenderer.get_CurrentFont()
   at MigraDoc.Rendering.ParagraphRenderer.CalcCurrentVerticalInfo()
   at MigraDoc.Rendering.ParagraphRenderer.InitFormat(Area area, FormatInfo previousFormatInfo)
   at MigraDoc.Rendering.ParagraphRenderer.Format(Area area, FormatInfo previousFormatInfo)
   at MigraDoc.Rendering.TopDownFormatter.FormatOnAreas(XGraphics gfx, Boolean topLevel)
   at MigraDoc.Rendering.FormattedCell.Format(XGraphics gfx)
   at MigraDoc.Rendering.TableRenderer.FormatCells()
   at MigraDoc.Rendering.TableRenderer.InitFormat(Area area, FormatInfo previousFormatInfo)
   at MigraDoc.Rendering.TableRenderer.Format(Area area, FormatInfo previousFormatInfo)
   at MigraDoc.Rendering.TopDownFormatter.FormatOnAreas(XGraphics gfx, Boolean topLevel)
   at MigraDoc.Rendering.FormattedHeaderFooter.Format(XGraphics gfx)
   at MigraDoc.Rendering.FormattedDocument.FormatHeader(HeaderFooterPosition hfp, HeaderFooter header)
   at MigraDoc.Rendering.FormattedDocument.FormatHeadersFooters()
   at MigraDoc.Rendering.FormattedDocument.MigraDoc.Rendering.IAreaProvider.GetNextArea()
   at MigraDoc.Rendering.TopDownFormatter.FormatOnAreas(XGraphics gfx, Boolean topLevel)
   at MigraDoc.Rendering.FormattedDocument.Format(XGraphics gfx)
   at MigraDoc.Rendering.DocumentRenderer.PrepareDocument()
   at MigraDoc.Rendering.PdfDocumentRenderer.PrepareDocumentRenderer(Boolean prepareCompletely)
   at MigraDoc.Rendering.PdfDocumentRenderer.PrepareRenderPages()
   at MigraDoc.Rendering.PdfDocumentRenderer.RenderDocument()

Author:  TH-Soft [ Fri Oct 13, 2017 7:28 pm ]
Post subject:  Re: Is PdfDocumentRenderer thread safe?

Version 1.50, latest beta?

Author:  vorobej [ Mon Oct 16, 2017 1:57 pm ]
Post subject:  Re: Is PdfDocumentRenderer thread safe?

In which version did you make it thread safe?

Author:  Thomas Hoevel [ Mon Oct 16, 2017 3:24 pm ]
Post subject:  Re: Is PdfDocumentRenderer thread safe?

With the beta versions of 1.50 the thread safety was improved.
viewtopic.php?f=2&t=832

Author:  vorobej [ Mon Oct 16, 2017 3:51 pm ]
Post subject:  Re: Is PdfDocumentRenderer thread safe?

We are on 1.50.4000-beta3b nuget package. It's not thread safe.

Author:  Thomas Hoevel [ Mon Oct 16, 2017 4:09 pm ]
Post subject:  Re: Is PdfDocumentRenderer thread safe?

Beta 3b is old and there are known bugs.

Maybe this workaround can help:
viewtopic.php?f=3&t=3315

Author:  vorobej [ Mon Oct 16, 2017 4:51 pm ]
Post subject:  Re: Is PdfDocumentRenderer thread safe?

But that is the latest nuget package available, am I missing anything?

A side topic: just recently I had an issue with .NET locks not working, and had to replace them with a Mutex, then it worked. Maybe see if you are having the same issue. When dumped to console, the addresses of the supposedly the same static lock object were different among threads.

Author:  vorobej [ Mon Oct 16, 2017 7:30 pm ]
Post subject:  Re: Is PdfDocumentRenderer thread safe?

Just re-tested with the latest beta and it did not work, nothing saved after rendering. So no, not thread safe.

Author:  TH-Soft [ Tue Oct 17, 2017 6:13 am ]
Post subject:  Re: Is PdfDocumentRenderer thread safe?

vorobej wrote:
A side topic: just recently I had an issue with .NET locks not working, and had to replace them with a Mutex, then it worked. Maybe see if you are having the same issue.
PDFsharp uses Locks to sync font creation/registration. If Locks do not work then PDFsharp is not thread-safe.
Using a single thread to register all required fonts, then using multiple threads to create PDF files would still be a suitable workaround. Replacing the Locks with Mutexes would be another option.

Author:  vorobej [ Tue Oct 17, 2017 2:01 pm ]
Post subject:  Re: Is PdfDocumentRenderer thread safe?

The point is that you may have to abandon Monitor and replace it with try/finally for a Mutex public read only instance field of a Document that renderer is working with, and that will make your code really thread safe.
Just dump the address of the object you lock on from each thread and see if that physical address is the same - if it's different, locks are not working.

Author:  vorobej [ Fri Oct 20, 2017 2:11 pm ]
Post subject:  Re: Is PdfDocumentRenderer thread safe?

It baffles me why this is even an issue, as in my case each thread has its own instance of Document, and its own instance of PdfDocumentRenderer. I would understand if there was an issue multi-threading the same instance of a Document, but in my case there should be no sections of code to protect with locks at all.
Can any one of the dev team comment on this, as what I am observing does not make any sense.

Author:  vorobej [ Fri Oct 20, 2017 4:13 pm ]
Post subject:  Re: Is PdfDocumentRenderer thread safe?

Okay, I am more and more convinced, that you are having the exact same issue I faced and described earlier: you are locking on a member of a static class. This did not work in the library I was fixing recently, and I used a Mutex, then it worked. But I ended up moving the object to lock on to the instance of the class we were working with and then it worked again. Do not lock on Lock.FontFactory - lock on the PdfDocumentRenderer or Document instance, and then it should work. And do not use Lock class, you are duplicating lock() function which is a cleaner equivalent, it does exactly the same try/finally with the Monitor without the overhead of writing boilerplate code. I am afraid I cannot spend any more time on this so do as you wish.

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/