PDFsharp & MigraDoc Foundation

PDFsharp - A .NET library for processing PDF & MigraDoc Foundation - Creating documents on the fly
It is currently Mon Feb 26, 2024 5:32 am

All times are UTC


Forum rules


Please read this before posting on this forum: Forum Rules



Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: Sun Nov 19, 2023 11:54 am 
Offline

Joined: Sun Nov 19, 2023 11:48 am
Posts: 5
Hi,

I have tried to call this code in parallel because otherwise it is very slow to render all pages:
Code:
using (XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Append))
{
    documentRenderer.RenderPage(gfx, pageIndex);
}


Sometimes it is working, so theoretically this is not a big problem.
But sometimes it fails with the following error:
Quote:
System.InvalidOperationException: Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct. at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
at System.Collections.Generic.Dictionary`2.set_Item(TKey key, TValue value)
at PdfSharp.Pdf.Advanced.PdfFontTable.GetFont(XFont font)
at PdfSharp.Pdf.PdfPage.GetFontName(XFont font, PdfFont& pdfFont)
at PdfSharp.Drawing.Pdf.XGraphicsPdfRenderer.GetFontName(XFont font, PdfFont& pdfFont)
at PdfSharp.Drawing.Pdf.PdfGraphicsState.RealizeFont(XFont font, XBrush brush, Int32 renderingMode)
at PdfSharp.Drawing.Pdf.XGraphicsPdfRenderer.Realize(XFont font, XBrush brush, Int32 renderingMode)
at PdfSharp.Drawing.Pdf.XGraphicsPdfRenderer.DrawString(String s, XFont font, XBrush brush, XRect rect, XStringFormat format)
at PdfSharp.Drawing.XGraphics.DrawString(String text, XFont font, XBrush brush, XRect layoutRectangle, XStringFormat format)
at PdfSharp.Drawing.XGraphics.DrawString(String s, XFont font, XBrush brush, Double x, Double y)
at MigraDoc.Rendering.ParagraphRenderer.RenderWord(String word)
at MigraDoc.Rendering.ParagraphRenderer.RenderText(Text text)
at MigraDoc.Rendering.ParagraphRenderer.RenderElement(DocumentObject docObj)
at MigraDoc.Rendering.ParagraphRenderer.RenderLine(LineInfo lineInfo)
at MigraDoc.Rendering.ParagraphRenderer.Render()
at MigraDoc.Rendering.DocumentRenderer.RenderHeader(XGraphics graphics, Int32 page)
at MigraDoc.Rendering.DocumentRenderer.RenderPage(XGraphics gfx, Int32 page, PageRenderOptions options)
at MigraDoc.Rendering.DocumentRenderer.RenderPage(XGraphics gfx, Int32 page)


Is it possible to make this specific Dictionary thread safe?
Or can I add all fonts before starting the rendering?

Thanks
Thomas


Top
 Profile  
Reply with quote  
PostPosted: Mon Nov 20, 2023 4:58 am 
Offline
PDFsharp Expert
User avatar

Joined: Sat Mar 14, 2015 10:15 am
Posts: 889
Location: CCAA
Are you using version 6.0.0?

See also:
http://forum.pdfsharp.net/viewtopic.php?f=2&t=832

_________________
Best regards
Thomas
(Freelance Software Developer with several years of MigraDoc/PDFsharp experience)


Top
 Profile  
Reply with quote  
PostPosted: Mon Nov 20, 2023 6:26 am 
Offline
PDFsharp Expert
User avatar

Joined: Sat Mar 14, 2015 10:15 am
Posts: 889
Location: CCAA
truthz03 wrote:
Is it possible to make this specific Dictionary thread safe?
PDFsharp is meant to be threadsafe and locks are used for font handling, but only a single thread must be used per document.
MigraDoc is not meant to be thread safe and just a single thread should be used to render all pages.

I don't have time to investigate this (non-)issue this month.
If you get it working with a few locks, please share your code changes here.
This is not my area of expertise and I cannot estimate how complicated this may get.

_________________
Best regards
Thomas
(Freelance Software Developer with several years of MigraDoc/PDFsharp experience)


Top
 Profile  
Reply with quote  
PostPosted: Mon Nov 20, 2023 11:43 am 
Offline

Joined: Sun Nov 19, 2023 11:48 am
Posts: 5
Thanks for your answer.
Yes I'm using 6.0.0

I have downloaded the source code from "Branch_v6.0.0" now and tried to fix the problem.
Changing these things inside the PdfFontTable class will fix the error above
Code:
        /// <summary>
        /// Gets a PdfFont from an XFont. If no PdfFont already exists, a new one is created.
        /// </summary>
        public PdfFont GetFont(XFont font)
        {
            var selector = font.Selector;
            if (selector == null)
            {
                selector = ComputeKey(font); //new FontSelector(font);
                font.Selector = selector;
            }

            var pdfFont = _fonts.GetOrAdd(selector, (selector) =>
            {
                PdfFont pdfFont;
                if (font.Unicode)
                    pdfFont = new PdfType0Font(Owner, font, font.IsVertical);
                else
                    pdfFont = new PdfTrueTypeFont(Owner, font);
                //pdfFont.Document = _document;
                Debug.Assert(pdfFont.Owner == Owner);
                return pdfFont;
            });
            return pdfFont;
        }

#if true
        /// <summary>
        /// Gets a PdfFont from a font program. If no PdfFont already exists, a new one is created.
        /// </summary>
        public PdfFont GetFont(string idName, byte[] fontData)
        {
            Debug.Assert(false);
            //FontSelector selector = new FontSelector(idName);
            string selector = null; // ComputeKey(font); //new FontSelector(font);
            var pdfFont = _fonts.GetOrAdd(selector, (selector) =>
            {
                PdfFont pdfFont;
                //if (font.Unicode)
                pdfFont = new PdfType0Font(Owner, idName, fontData, false);
                //else
                //  pdfFont = new PdfTrueTypeFont(_owner, font);
                //pdfFont.Document = _document;
                Debug.Assert(pdfFont.Owner == Owner);
                return pdfFont;
            });
            return pdfFont;
        }
#endif

        /// <summary>
        /// Map from PdfFontSelector to PdfFont.
        /// </summary>
        readonly ConcurrentDictionary<string, PdfFont> _fonts = new ConcurrentDictionary<string, PdfFont>();

but than I get other errors.

It would be nice to be able to render pages of a single document in parallel, but I think there has to be more changes.

Maybe this could be a feature for a later version


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 6 guests


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:  
Privacy Policy, Data Protection Declaration, Impressum
Powered by phpBB® Forum Software © phpBB Group