Loading a PDF in a BackgroundWorker = AccessViolation

Discussions about PDF management.
Post Reply
j2df
Posts: 11
Joined: Fri Nov 01, 2013 5:19 pm

Loading a PDF in a BackgroundWorker = AccessViolation

Post by j2df » Fri Nov 01, 2013 5:51 pm

Hello,

*I'm using GDPicture.Net 10*

For the purpose of the redesign of one of our application, we decided to give GDPicture a chance. I've implemented it in the new version and it's working quite well. But I have an issue when trying to load a PDF from a different thread. What I do when loading a PDF is the following :

- I create a thumbnail of the page which is kept in memory (I set the DPI to 11 in this case) using this function :

Code: Select all

 Private Function CreatePageImage(dpi As Single) As CachedBitmap
            _PDFDocument.SetMeasurementUnit(PdfMeasurementUnit.PdfMeasurementUnitPoint)

            Dim gdImage As New GdPicture10.GdPictureImaging
            Dim imageID As Integer

            Try

                imageID = _PDFDocument.RenderPageToGdPictureImage(dpi, False, True)
                If imageID = 0 Then Return Nothing

                gdImage.ConvertTo24BppRGB(imageID)

                Return System.Windows.Media.Imaging.BitmapSource.Create(gdImage.GetWidth(imageID),
                                                                        gdImage.GetHeight(imageID),
                                                                        gdImage.GetHorizontalResolution(imageID),
                                                                        gdImage.GetVerticalResolution(imageID),
                                                                        PixelFormats.Bgr24, Nothing,
                                                                        gdImage.GetBits(imageID),
                                                                        gdImage.GetStride(imageID) * gdImage.GetHeight(imageID),
                                                                        gdImage.GetStride(imageID))

            Finally
                If imageID > 0 Then gdImage.ReleaseGdPictureImage(imageID)
                gdImage.Dispose()
                _PDFDocument.SetMeasurementUnit(PdfMeasurementUnit.PdfMeasurementUnitInch)
            End Try
        End Function
- And I create a 200 DPI version of the page which I save in a temporary folder, I use it to display the pages of my PDF (I save it because it's faster to load the pages afterwards and on big PDF the memory usage could be quite huge if I kept everything in memory)

Code: Select all

 Public Function SavePageImage(index As Integer, fullPath As String) As Boolean
            _PDFDocument.SetMeasurementUnit(PdfMeasurementUnit.PdfMeasurementUnitPoint)

            Dim gdImage As New GdPicture10.GdPictureImaging
            Dim imageID As Integer = _PDFDocument.RenderPageToGdPictureImage(My.Settings.DPI, False, True)

            If imageID = 0 Then Return False

            Try
                gdImage.ConvertTo24BppRGB(imageID)
                Using bmp As System.Drawing.Bitmap = gdImage.GetBitmapFromGdPictureImage(imageID)
                    bmp.Save(fullPath, System.Drawing.Imaging.ImageFormat.Png)
                End Using

                Return True
            Finally
                gdImage.ReleaseGdPictureImage(imageID)
                gdImage.Dispose()
                _PDFDocument.SetMeasurementUnit(PdfMeasurementUnit.PdfMeasurementUnitInch)
            End Try
        End Function
And it's working fine. I'm calling these two function directly from a separate thread, I get the percentage of the loading and when the loading's over everything works just fine. But if the user wants to cancel the loading, I get an error. The thing is, it's not only when I cancel the thread, if I just launch a msgbox on the main thread while working with one of these two function in a different thread, my app crashes. I tried removing the calls to these two functions, it doesn't crash anymore!

I can deal with the crashing, I just catch the exception the BackgroundWorker is giving me and depending on the error (I get a GDI+ Exception or a NullReferenceException depending on where the thread is when I click cancel) and I deal with it. But sometimes I get an AccessViolationException (the "Attempted to read or write protected memory" error) on the line :

Code: Select all

_PDFDocument.RenderPageToGdPictureImage(My.Settings.DPI, False, True)
...which is an unhandled exception in my code and it doesn't get caught by my "try ... catch", in debug it indicates that there's an error and I can continue debugging, but in production my app is crashing.

Again, I can catch the unhandled exception and show a message to the user idicating there was a problem and then let the App quites, but that's not what I want, I want to be able to catch this exception and deal with it. Meaning cancelling the loading of my pdf and leting the user continue working with my app. Or I want to know if there's a way to keep these functions from crashing when I try cancelling the thread (in this case the problem arises when doing any action while the backgroundWorker is running).

I know it's quite a bizarre problem, but I've spent my entire day on it today and I still don't know why these problems occurs.

User avatar
Loïc
Site Admin
Posts: 5881
Joined: Tue Oct 17, 2006 10:48 pm
Location: France
Contact:

Re: Loading a PDF in a BackgroundWorker = AccessViolation

Post by Loïc » Fri Nov 01, 2013 7:47 pm

Hello,

Well, based on the explanations I can only suggest to check that you are not trying to access to the same memory area from different threads.
If you are still not able to fix your problem we can help in certain conditions that are explained on our support policies that you can find here: https://www.gdpicture.com/support/policies.php

To sum-up: Reproduce your problem in a very small application that you can send to our team trough our helpdesk plateform located here: http://support.orpalis.com
So we will be able to easily explain you what you are doing wrong.

With best regards,

Loïc Carrère

j2df
Posts: 11
Joined: Fri Nov 01, 2013 5:19 pm

Re: Loading a PDF in a BackgroundWorker = AccessViolation

Post by j2df » Tue Nov 05, 2013 10:03 am

Hi Loïc,

I feel quite stupid about this problem, I just solved it (without even trying to solve it :lol: ).
What was happening is that I was creating my document this way : I have a DocumentViewModel which defines a Document in my application, this DocumentViewModel binds to a DocumentView. When creating a new document I was adding the DocumentViewModel to an ObservableCollection(Of DocumentViewModel), the document was immediately added to the VisualTree (since I was using ObservableCollection) and every action I was doing while loading the file (loading the pages of the PDF, creating thumbnails and applying them to my bound properties, etc.) was bound the the UI View.

I changed this behaviour by creating my DocumentViewModel, initializing it (thumbnail, etc.) and adding it to the VisualTree only in the end of the loading (which is, by logic, a far better solution). I did so to eliminate some lags in my UI while the loading was taking place, but not only did the lag disappear, but all the cross threads exceptions I had before and I mentionned in this subject where gone. Apparently it was cross threads error, in a weird way (the UI thread was updating while the background thread was creating the pages).

Anyway thanks for your quick answer, I'm glad everything worked out fine, cause your library is quite powerful and very helpful!

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests