2011-07-08 15 views
12

テキストを切り捨てずに、指定された文字列とフォントに使用する最大サイズを特定のボックスに入力するカスタムメソッドがあります。これをテストするために、いくつかの異なる文字列といくつかの異なるフォントを繰り返し、Parallel.Forループでそれらのバッチを実行するサービスを作成しました。このサービスが実行されている場合、システム上のすべてのCPUコアは%90-%100になります。 8時間または9時間実行すると、例外がスローされます。それでもほとんどの場合は動作しますが、時折例外が発生したり、例外が破裂することがあります。"操作が正常に完了しました"例外

最も内側の例外には「操作が正常に完了しました」というメッセージがあり、FormattedTextオブジェクトのWidthIncludingTrailingWhitespaceアクセサから発生しています。コールスタックは、次のようになります。これを研究して

at MS.Win32.UnsafeNativeMethods.RegisterClassEx(WNDCLASSEX_D wc_d) 
    at MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks) 
    at System.Windows.Threading.Dispatcher..ctor() 
    at System.Windows.Threading.Dispatcher.get_CurrentDispatcher() 
    at System.Windows.Media.TextFormatting.TextFormatter.FromCurrentDispatcher(TextFormattingMode textFormattingMode) 
    at System.Windows.Media.FormattedText.LineEnumerator..ctor(FormattedText text) 
    at System.Windows.Media.FormattedText.DrawAndCalculateMetrics(DrawingContext dc, Point drawingOffset, Boolean getBlackBoxMetrics) 
    at System.Windows.Media.FormattedText.get_Metrics() 
    at System.Windows.Media.FormattedText.get_WidthIncludingTrailingWhitespace() 
    ...My Library Here... 

、私はundisposed描画オブジェクト(グラフィックス、アイコンなど)は、このための一般的な原因ですが、私は使用中の使い捨てのオブジェクトを見つけることができなかったことがわかりました。テキストサイジングコードはWPFクラス(FontFamily、FormattedText、およびTypeface)を使用し、いずれもIDisposableを実装しません。

私はperfmonでプロセスを監視していますが、メモリ使用量、ハンドル数、スレッド数は非常にばらつきがありますが、決して制御不能になることはありません。これはおそらくハンドルリークではないことを私に伝えます。それ以外に何ができますか?

UPDATE:私は数日間、重要な変更を加えてテストを実行しています。これは、並列の代わりに定期的に実行しています。それはまだ墜落しておらず、perfmonはほとんど変化のない水平線を示しています。これは並列化の問題で、WPFのテキストレンダリングではないでしょうか?

答えて

0

WPFが別の新しいDispatcherのネイティブWin32ウィンドウハンドルを割り当てようとしたときに例外が発生したようです。おそらくプロセスの最大ハンドル数に達しているでしょうか?

各繰り返しでガベージコレクションを強制しようとしましたか?ほとんどのWPFクラスはIDisposableを実装していませんが、WPF内で管理される未管理のリソースを引き続き使用します。

私は想像することができるオーバーフローのための別の方法があります。 CurrentDispatcherプロパティは、スレッドごとに新しいDispatcherを作成します。 InvokeShutdownが呼び出されるまで、すべてのディスパッチャは停止しません。したがって、Dispatcherが動作するスレッドは、Windowが存在しないため、終了ボタンを押すことがないため、決して終了しません。おそらくParallel.Forの実装で、次の反復のために新しいスレッドを割り当てるようにします。これには、別の新しいDispatcherと別の新しいハンドルが必要です。残念ながら、Parallelの使用経験はあまりないので、これは単なる仮定です。

+0

私はperfmonをプロセス上で実行していますが、ハンドルの使用状況は大きく上下しています。これは上昇傾向がないため、問題ではないと思います。私は定期的にガベージコレクションを強制しようとしました - それは役に立たなかった。その最後の提案は面白いです。パーフォーマンはスレッドの上昇トレンドを示していませんが、これはどれも良いリードです。ありがとう! –

関連する問題