Ich habe einen FixedDocument-Bericht erstellt, der monatlich gedruckt werden soll. Er wird im Durchschnitt etwa 350 Seiten lang sein, wobei etwa die Hälfte der Seiten ~200kb jpeg-Bilder sind. Der Bericht wird im DocumentViewer gut angezeigt, aber ich habe Probleme, wenn ich versuche, ihn zu drucken.
Bei der Verwendung von
DocumentViewer1.Print()
Wenn ich nur versuche, das erste Drittel der Monatsdaten zu drucken, z. B. 120 Seiten, funktioniert das problemlos. Wenn ich aber versuche, den ganzen Monat zu drucken, erhalte ich etwa bei der 160. Seite folgende Fehlermeldung
System.OutOfMemoryException: Insufficient memory to continue the execution
of the program.
at System.Windows.Media.Imaging.BitmapSource.CriticalCopyPixels(Int32Rect
sourceRect, IntPtr buffer, Int32 bufferSize, Int32 stride)
at System.Windows.Media.Imaging.BitmapSource.CriticalCopyPixels(Int32Rect
sourceRect, Array pixels, Int32 stride, Int32 offset)
at Microsoft.Internal.GDIExporter.CGDIBitmap.Load(BitmapSource pBitmap,
Byte[] buffer, PixelFormat LoadFormat)
at
Microsoft.Internal.GDIExporter.CGDIRenderTarget.DrawBitmap(BitmapSource
pImage, Byte[] buffer, Rect rectDest)
at Microsoft.Internal.GDIExporter.CGDIRenderTarget.DrawImage(BitmapSource
source, Byte[] buffer, Rect rect)
at
Microsoft.Internal.AlphaFlattener.BrushProxyDecomposer.Microsoft.Internal.Al
phaFlattener.IProxyDrawingContext.DrawImage(ImageProxy image, Rect dest,
Geometry clip, Matrix trans)
at
Microsoft.Internal.AlphaFlattener.PrimitiveRenderer.RenderImage(ImageProxy
image, Rect dest, Geometry bounds, Boolean clipToBounds, Int32 start, Matrix
trans, String desp)
at
Microsoft.Internal.AlphaFlattener.PrimitiveRenderer.RenderImage(ImageProxy
image, Rect dest, Geometry clip, Matrix trans, String desp)
at Microsoft.Internal.AlphaFlattener.Flattener.AlphaRender(Primitive
primitive, List`1 overlapping, Int32 overlapHasTransparency, Boolean
disjoint, String desp)
at
Microsoft.Internal.AlphaFlattener.Flattener.AlphaFlatten(IProxyDrawingContex
t dc, Boolean disjoint)
at Microsoft.Internal.AlphaFlattener.Flattener.Convert(Primitive tree,
ILegacyDevice dc, Double width, Double height, Double dpix, Double dpiy,
Nullable`1 quality)
at Microsoft.Internal.AlphaFlattener.MetroDevice0.FlushPage(ILegacyDevice
sink, Double width, Double height, Nullable`1 outputQuality)
at Microsoft.Internal.AlphaFlattener.MetroToGdiConverter.FlushPage()
at
System.Windows.Xps.Serialization.NgcSerializationManagerAsync.EndPage()
at
System.Windows.Xps.Serialization.NgcFixedPageSerializerAsync.EndPersistObjec
tData(Boolean isManualStartDoc)
at
System.Windows.Xps.Serialization.NgcFixedPageSerializerAsync.AsyncOperation(
NGCSerializerContext context)
at
System.Windows.Xps.Serialization.NgcSerializationManagerAsync.InvokeSaveAsXa
mlWorkItem(Object arg)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate
callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object
source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at
System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object
state)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedClea
nup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state, Boolean
ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32
msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam,
IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate
callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object
source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority
priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr
wParam, IntPtr lParam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.Unsaf
eNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID,
Int32 reason, Int32 pvLoopData)
at
System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32
reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32
reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(ApplicationContext context)
at
Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun(
)
at
Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoAppl
icationModel()
Dann dachte ich, ich könnte das Problem umgehen, indem ich einfach 30 Seiten auf einmal drucke, indem ich das Dokument in kleine 30-seitige Dokumente aufteile:
Dim dlg = New PrintDialog()
If dlg.ShowDialog() = True Then
Dim PageCounter As Int32 = 0
Dim ListOfDocs As New List(Of FixedDocument)
Dim CurrentFixedDoc As New FixedDocument
For Each FixedSizePag As FixedPage In PrintListOfPages
Dim FixedSizedPageConten As PageContent = New PageContent
CType(FixedSizedPageConten, IAddChild).AddChild(FixedSizePag)
CurrentFixedDoc.Pages.Add(FixedSizedPageConten)
PageCounter = PageCounter + 1
If PageCounter >= 30 Then
ListOfDocs.Add(CurrentFixedDoc)
PageCounter = 0
CurrentFixedDoc = New FixedDocument
End If
Next
If CurrentFixedDoc.Pages.Count > 0 Then
ListOfDocs.Add(CurrentFixedDoc)
End If
For Each docum In ListOfDocs
dlg.PrintDocument(docum.DocumentPaginator, "Testing - Part " & (ListOfDocs.IndexOf(docum) + 1) & " of " & ListOfDocs.Count)
Next
End If
Aber das führte genau zu demselben Fehler. Ich habe versucht, hundert Seiten ab der Monatsmitte und gegen Ende des Monats zu drucken, und das funktioniert. Es muss also eher an der Menge der Seiten als an einem bestimmten Bild liegen (die Bilder sind nur jpegs, alle aus einer Quelle, maximale Größe 400kb).
Wenn ich den Speicherverbrauch beim Drucken von 30 Seiten auf einmal beobachte, sehe ich
Start = 96Mb
30 pages = 367Mb
60 pages = 588Mb
90 pages = 825Mb
120 pages = 1003Mb
150 pages = 1238Mb
stürzt dann bei der nächsten Charge mit 1281Mb ab
Ich habe es auf einem echten Drucker und dem XPS-Windows-Drucker getestet. Als ich diese Speicherwerte notiert habe, habe ich gewartet, bis jeder Abschnitt vollständig aufgespult und gedruckt war.
Ich kann nicht verstehen, warum sich das so aufbaut, wenn ich sie in einzelne Dokumente aufteile. Ich muss etwas entsorgen, aber ich bin nicht sicher, was?