2011-02-11 24 views
4

私は、xmlファイルをXPathDocumentにロードするメソッドを呼び出す非同期デリゲートを使用しています。 xmlが大きすぎてメモリに収まらない場合は、ロードが完了しません。 xmlファイルがXPathDocumentに正常に読み込まれた場合、以下のコードが動作します。私はasyncXpath.EndInvoke(result)ステートメントを実行し、CreateDocumentメソッドを終了させるタイマーイベントを使用することができましたが、XPathDocumentのロードを停止しません。私の結論は、私ができる唯一のことはアプリケーションを終了するためにApplication.Endステートメントを発行することです。 XPathDocumentの読み込みなど、ブラックボックス操作を停止する方法を知っている人はいますか?「ブラックボックス」操作を停止するにはどうすればよいですか?

delegate bool AsyncXpathQueryCaller(string xmlfile 

bool found = false; 
AsyncXpathQueryCaller asyncXpath = new 
AsyncXpathQueryCaller(CreateDocument); 
IAsyncResult result = asyncXpath.BeginInvoke(xmlfile, null, null); 
while (!result.IsCompleted) 
{ 
result.AsyncWaitHandle.WaitOne(100, false); 

} 
found = asyncXpath.EndInvoke(result); 


private bool CreateDocument (string xmlfile) 
{ 
XPathDocument doc = new XPathDocument(xmlfile); 
} 
+0

ドキュメントが大きい場合は、前方読み取り専用リーダーを使用してデータを読み取り/処理することをおすすめします。これは速くなり、必要に応じてファイルを読み込む際に中断することもあります。 –

+0

@Tim - XPathDocumentオブジェクトを作成する方法は非常に多くあり、そのすべてはコンストラクタがファイルの読み込みを制御できるようにします。 – KeithS

+0

@KeithS - 私はXmlReaderの詳細を考えていました...問題のドキュメントが大きければ、一度に必要な場合はチャンク、変換/解析/ etcなどで読み取ることができます。このケースに合っているかどうかわからないので、答えではなくコメントを投稿したのです。 –

答えて

1

あなたはそれをロードしようとする前に、FileInfoを使用してサイズを確認するでしょうか?それが大きすぎる場合は、それをスキップしてください。このような

何か:

FileInfo fi = new FileInfo(xmlfile); 
if(fi.Length < /*some huge number*/) 
{ 
    //load the file 
} 
+1

私にとっては速すぎます。 – KeithS

+0

「私にとっては速すぎますか?」 lol – Amy

+0

「あまりにも大きい」と定義できれば、私はあなたの答えをアップヴォートするでしょう。私はあなたができることを疑うので、私はdownvoteに誘惑される。 – Gabe

0

あなたがのFileStreamを宣言し、コンストラクタにそれを与える、しかし、あなたが前に、そのLengthプロパティを見て、それが長すぎるなら、単にエラーを返すことができます。

+0

とxmlの長さが長すぎるかどうかを知る方法はありません。それはファイルの長さ以上のXMLの構造と内容に依存します。私はXMLの任意の特性の事前知識を持っていない何かである可能性があります。 –

+1

私は同意しません。ファイルの長さはファイルの内容に比例します。比較的小さいサイズのファイルがあなたの顔に爆発する原因は2つあります。パーザにとってネストされたタグ(そう思わないでしょう)と再帰的なエンティティの定義が解析される「10億の笑い」型の悪用Bajillion文字の値に変換します。 – KeithS

+0

ファイルが使用可能なメモリに対して大きすぎる可能性があります。 XPathDocumentが作成されたときに.netが作成するスレッドを強制終了する方法はありますか? –

0

EDIT:私はちょうどKeithSが良い答えに近づいたことに気づいた。基本的な考え方は、FileStreamをラップするStreamを受け入れるXPathDocument constructorと呼ぶことです。あなたが渡したオブジェクトは、関数を実装して、ラップされたFileStreamRead関数を呼び出すか、操作がタイムアウトした場合に例外をスローする必要があります。ここで

class XmlStream : FileStream 
{ 
    DateTime deadline; 

    public XmlStream(string filename, TimeSpan timeout) 
      : base(filename, FileMode.Open) 
    { 
     deadline = DateTime.UtcNow + timeout; 
    } 

    public override int Read(byte[] array, int offset, int count) 
    { 
     if (DateTime.UtcNow > deadline) 
      throw new TimeoutException(); 
     return base.Read(array, offset, count); 
    } 
} 

秒1の後にいくつかdocumentで読み取るコードが、回だ:

bool found = true; 
    using(var stream = new XmlStream(document, TimeSpan.FromSeconds(1))) 
    try 
    { 
     xpath = new XPathDocument(stream); 
    } 
    catch (TimeoutException) 
    { 
     found = false; 
    } 

があなたの代わりにBeginInvokeを行うための別のスレッドを作成する場合は、あなただけ中止することができ、ここでのサンプルコードを示しますタイマーが刻々と変化する(または誰かが "キャンセル"をクリックする)スレッド。スレッドを中止するのは一般的にはお勧めできませんが、ロックを保持しているか、グローバルデータが不整合な状態になっている可能性があります。この場合、スレッドがロックを保持していないか、ここで

は、前のサンプルと同じ処理を行い、このメソッドのコードです:

bool found = false; 
    thread = new Thread(() => 
    { 
     xpath = new XPathDocument(document); 
     found = true; 
    }); 
    thread.Start(); 
    thread.Join(TimeSpan.FromSeconds(1)); 
    thread.Abort(); 

独自のアプリケーションドメインでスレッドを中断すると不快なら、あなたは別のアプリケーションドメイン内の文書を作成することができますし、それに時間がかかる場合は、AppDomain.Unloadとお電話ください。それにはマーシャリングが必要ですが、オーバーヘッドがあまりありません。

プロセスを強制終了できる究極の方法は、プロセスを別のプロセスで実行し、それにアクセスするための何らかのリモートインターフェイスを使用することです。しかし、実行可能ファイルを見つけること、パラメータを渡すこと、いくつかのユーザーを終了させることなどを心配する必要があるので、おそらく他のオプションももっと厄介です。

+0

あなたはスレッドを中止するのは良くないと言っても間違いありません。私はこれが最良の選択肢であることに同意しません... –

+0

@Abe Miessler:私はあなたに同意しますが、これはOPの質問に答えるものであり、他はアドバイスを与えることに注意してください。 –

+0

私はスレッドを中止するためにあなたのタイマーの提案を試みました。呼び出されたメソッドは停止しますが、xpathドキュメントをロードする「ブラックボックス」プロセスが続行されます。タスクマネージャは3Mbのメモリしか残さない(約800Mbで開始)。 XMLファイルサイズは266Mbです。多分xmpathdocumentは私のアプリケーションではなく、.netによって扱われる別のスレッドにロードされます。私もapplication.exitを試したが、それでもそれを止めない。 –

0

Abe Miesslerによって提案されたように、ファイルサイズをXPathDocumentにロードしようとする前にチェックすることは賢明です。

どのように制限する必要がありますか

厳密な規則はありませんが、ファイルサイズに5を掛けて、結果がXmlDocumentが読み込み/解析されるために必要なメモリに近いと言う人がいると聞いています。

+0

OK、そうしましょう。 'XmlDocument'がどれくらいのメモリを使用するかを決めることができます。 – Gabe

+0

@Gabe:ほとんどのオペレーティングシステムは、特定の関数/ APIを介して利用可能な現在の空きメモリに関する情報を提供します –

+0

"現在の空きメモリ"とは何ですか?物理メモリは使用可能ですか?仮想メモリ?とにかくそれは何が良いですか? XMLの処理が完了するまでに、より多くのメモリーを解放または割り振ることができました。 – Gabe

関連する問題