2012-01-30 116 views
1

我創建了一個每月打印的FixedDocument報告。它的平均長度約爲350頁,大約一半的頁面是〜200kb的jpeg圖像。該報告在DocumentViewer中很好地顯示,但在嘗試打印時遇到問題。WPF打印大型報告導致OutOfMemoryException

當使用

DocumentViewer1.Print() 

如果我只是嘗試和打印個月的數據如的前三分之一。它120頁,它工作正常。 但如果我嘗試了整整一個月,在大約第160頁我收到以下錯誤

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() 

我當時以爲由文檔分成小30頁我想通過只是一次打印30頁戰勝它的方法文件使用:

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 

但是,這只是造成了完全相同的錯誤。我已經嘗試從中點開始打印一百頁,並且在月末之前就可以打印,因此它必須是頁面的大小而不是特定的圖像(圖像僅來自一個源,最大尺寸爲400kb)。

觀看的內存量,同時在打印時30頁使用我看到

Start = 96Mb 
    30 pages = 367Mb 
    60 pages = 588Mb 
    90 pages = 825Mb 
    120 pages = 1003Mb 
    150 pages = 1238Mb 

則下一批崩潰在1281Mb

我真正的打印機和XPS上測試windows打印機。當我記下這些內存值時,我一直等到每個部分完全被假脫機打印。

我不明白爲什麼當我將它們分解爲單獨的單獨文檔時,它就像這樣建立起來。我必須處理一些東西,但我不確定是什麼?

+0

我甚至試過GC.Collect的() GC.WaitForPendingFinalizers()仍然會產生同樣的錯誤。有任何想法嗎? – SpeedBird527 2012-03-31 09:44:47

+0

我們有類似的問題......您是否找到任何解決方法? – Mike 2012-08-23 10:46:29

回答

0

您應該爲每個文件生成10個頁面(每個文件有一個FixedDocument),然後將這些文件合併爲一個文件(您將擁有一個FixedDocumentSequence)。接下來你打印這個FixedDocumentSequence。我相信這個解決方案不會消耗太多內存。

System.Windows.Xps.XpsDocumentWriter.Write(System.Windows.Documents.FixedDocumentSequence文檔序列)