0

問題:大きなPDFファイル(50Mb、1500ページ)を使用してLoadFile()を何回か(10-20回で十分)非同期で呼び出すと、OutOfMemory例外がかなり早く発生します。 EndInvoke()の後にGC.Collect()を呼び出すと、問題が解決されます。メソッドを非同期で何回か呼び出すとOutOfMemory例外が発生する

同期呼び出しは素晴らしいです(メモリリークは発生しません)。

GC.Collect()を直接呼び出さずに解決する方法はありますか?

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void Open_Click(object sender, EventArgs e) 
    { 
     MethodInvoker invoker = this.LoadFile; 
     AsyncCallback callback = CallBack; 

     invoker.BeginInvoke(callback, null); 

     // Synchronous call. 
     // LoadFile(); 
    } 

    private void CallBack(IAsyncResult ar) 
    { 
     AsyncResult result = (AsyncResult)ar; 

     MethodInvoker invoker = (MethodInvoker)result.AsyncDelegate; 
     invoker.EndInvoke(ar); 

     // GC.Collect(); 
    } 

    private void LoadFile() 
    { 
     byte[] fileBytes = File.ReadAllBytes(@"c:\50mb.pdf"); 

     // Third party OCX component for viewing PDF files. 
     this.pdfOcxViewer.OpenBuffer(fileBytes, fileBytes.Length, ""); 
     this.pdfOcxViewer.CloseFile(); 
    } 
} 

答えて

0

実際はありません。あなたがそれを必要としていることが分かっているときは、十分に時間を計られたGC.Collectが受け入れられます。私はそれをLoadFile関数の最後に移動することをお勧めしますが(メモリを消費するタスクのソースに近い方が良い)

1

おそらく、爆弾でE_OUTOFMEMORYを返すActiveXコンポーネントです。 OOMに変換されます。問題は、このコードを非同期に実行すると、そのコンポーネントの複数のインスタンスが実行されていることです。 50 MBのpdfファイルでは、おそらく数百MBの非管理メモリが必要になります。

GC.Collect()呼び出しは偶発的に動作します。 fileBytes配列を解放します。それらはかなり大きく、ラージオブジェクトヒープに配置されます。それらをリリースするには完全なGCが必要です。あなたのCollect()コールは、ActiveXコンポーネントにWindowsヒープマネージャーからアンマネージメモリを奪うための何らかの呼吸スペースを与えます。

ここでは、32ビットプロセスの基本的なメモリ制限にぶつかっています。このコンポーネントのインスタンスの数を制限して、あまりにも多くのメモリを浪費させないようにする必要があります。とにかくActiveXコンポーネント上でのスレッド処理はめったに動作せず、COMはSTAスレッドへの呼び出しをマーシャリングします。

+0

なぜ、コンポーネントの複数のインスタンスが実行されていると思いますか?コンポーネントをラップするコントロールは、明らかに単一のインスタンスを持っています。 – Corvin

関連する問題