PDFsharp & MigraDoc Foundation

PDFsharp - A .NET library for processing PDF & MigraDoc Foundation - Creating documents on the fly
It is currently Tue Dec 12, 2017 4:49 am

All times are UTC




Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: Wed Mar 09, 2016 10:20 pm 
Offline

Joined: Tue Jan 19, 2016 12:16 am
Posts: 7
Hello,

I am running PDF sharp latest version (PDFsharp-1_50-beta3b.zip) under Visual Studio 2015.

I seem to be running into a problem having two threads writing using PDFsharp.

Inside of XGlyphTypeface.cs, one thread is going in there and calling

GlyphTypefaceCache.AddGlyphTypeface(glyphTypeface);, added in the glyphTypeface into the cache.

This is being done while the second thread is already past this point:

if (GlyphTypefaceCache.TryGetGlyphTypeface(typefaceKey, out glyphTypeface))

meaning that it will also call GlyphTypefaceCache.AddGlyphTypeface(glyphTypeface);,when it already exists inside of the Dictionary, thus causes an exception when trying to render a document.

An item with the same key has already been added. 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 MigraDoc.Rendering.FontHandler.FontToXFont(Font font, PdfFontEncoding encoding)
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.FormattedDocument.Format(XGraphics gfx)
at MigraDoc.Rendering.DocumentRenderer.PrepareDocument()
at MigraDoc.Rendering.PdfDocumentRenderer.PrepareDocumentRenderer(Boolean prepareCompletely)
at MigraDoc.Rendering.PdfDocumentRenderer.RenderDocument()

A bit of background info:

I am using GlobalFontSettings.FontResolver to resolve fonts, which creates and resolves these fonts. (public class EzFontResolver : IFontResolver) I am using WPF I believe as well.

I'm not sure if this is an issue with my implementation or the PDFsharp library itself with multiple threads/tasks. Any help would be appreciated.

My solution for this bug at the moment is to use all the fonts in the font resolver to render a dummy document in a single thread populating the dictionary before allowing multiple threads to render PDF documents.


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 10, 2016 9:09 am 
Offline
empira Employee
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 2740
Location: Cologne, Germany
Hi!

Thanks for the feedback. We need more "locks" in the code to prevent this problem.
We do have some locks already, but this case slips through. We'll add more locks with the next release.

Good to know you found a workaround.

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Wed Apr 13, 2016 10:07 am 
Offline

Joined: Wed Apr 13, 2016 10:00 am
Posts: 1
Hello seeker25,

can you please share the code you use for rendering the dummy document in order to avoid the "An item with the same key has already been added" exception thrown when using PDFSharp in multithreaded app?

Thank you in advance.


Top
 Profile  
Reply with quote  
PostPosted: Fri Apr 22, 2016 9:11 pm 
Offline

Joined: Tue Jan 19, 2016 12:16 am
Posts: 7
Code:

                //Setup for PdfSharp to use custom fonts.
                var fontResolver = EzFontResolver.Get;
                GlobalFontSettings.FontResolver = fontResolver;

fontResolver.AddFont("Courier New", XFontStyle.Regular, fontPath, true, true);

 var fontNames = new List<string>
                {
                    "courier new"
                };

   foreach (var fontName in fontNames)
                {
                    new XFont(fontName, 20, XFontStyle.Regular);

                    document.Styles.AddStyle(fontName, "Normal");
                    var style = document.Styles[fontName];
                    style.Font = new Font(fontName);

                    var styleName = fontName;
                    var para = document.AddSection().AddParagraph("H", styleName);
                    para.Format.Font.Bold = true;

                    para = document.AddSection().AddParagraph("H", styleName);
                    para.Format.Font.Italic = true;

                    para = document.AddSection().AddParagraph("H", styleName);
                    para.Format.Font.Bold = true;
                    para.Format.Font.Italic = true;

                }

                var pdfRenderer = new PdfDocumentRenderer { Document = document};
                pdfRenderer.RenderDocument();
                pdfRenderer.PdfDocument.Close();
                pdfRenderer.PdfDocument.Dispose();



This should populate the static dictionary.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group