わかりました、それで私はついにそれを理解しました。
まず、画像に関する限り、CLR は a に割り当てられているメモリの量を明らかに知らないため、Drawing.Image
破棄するときに次のように伝える必要があります。
'It's 4 bytes per pixel with RGBA
'Use Drawing.Image.PixelFormat to get
'the number of bytes if you don't know
Dim countBytes as long = 4 * img.Width * img.Height
'Let the CLR know of the memory we want to free
if countBytes > 0 then GC.AddMemoryPressure(countBytes)
'Get rid of the image
img.Dispose()
img = Nothing
'Free up the unused memory
GC.Collect()
'Tell the CLR we took care of it
GC.RemoveMemoryPressure(countBytes)
さて、CodeProject サンプルの PDF ライブラリは、かなり難しいものでした。
まず、ラッパーを保持するフォームのイベント、またはラッパーを保持するクラスのメソッドのいずれかで、オブジェクトのDispose
メソッドを呼び出すようにしてください。PDFWrapper
FormClosed
Finalize
しかし、PDFWrapper
実際には、そこから取得した画像をキャッシュしているようです。そのため、PDF のページをめくると、PDF 全体の画像がキャッシュされるまでメモリ使用量が増加します。これらの画像を使用して PDF を 300DPI で印刷する場合、これはさらに大きな問題になります (1.5GB のメモリを使用すると、60 ページ以上の PDF の終わりに向かってメモリ不足エラーが発生します)。
私が知る限り、このオブジェクトには「キャッシュをクリア」するメソッドはありません。しかし、それを機能させるために使用したハックは、必要な画像を取得した後に 1DPI で画像を取得し、上記のようにガベージ コレクションを実行することでした。これにより、キャッシュされたメモリが間接的に解放されます。ただし、前と同様に、使用したバイト数を CLR に通知する必要があります。上と同じ計算です。
しかし、もう1つ問題があります。オブジェクトは実際にはPDFWrapper
別のスレッドで画像を取得しているようです。そのため、300DPI の画像をリクエストした後に別の 1DPI の画像をリクエストすると、印刷する 300DPI の画像が必要なときに、混乱してランダムに 1DPI の画像を吐き出してしまいます。したがって、これに対する回避策は次のとおりです。
Dim img As System.Drawing.Image
img = AFPDFLibUtil.GetImageFromPDF(pdfWrapper, currentPage, DPI)
'Wait for PDFWrapper to finish rendering
Dim sw As New Stopwatch()
sw.Start()
While _pdfWrapper.IsBusy
If sw.ElapsedMilliseconds < TimeoutMS Then
System.Threading.Thread.Sleep(10)
Else
Throw New Exception("This page took too long to render.")
End If
End While
sw.Stop()
sw.Reset()
そして、そこに行きます。おそらくそれが、CodeProject サンプルで別の DLL を使用して印刷を行っている理由です。ただし、PDFWrapper
オブジェクトは からの読み取りをサポートしIO.MemoryStream
ています。そのプロジェクトの他のインクルードはサポートしていないと思います。
これを読んでいる人は誰でも幸せにコーディングしてください!