RSS フィードから最新のニュース ヘッドラインを取得するサービスで、WPF FormattedText オブジェクトを使用してテキスト サイズを決定します。取得するテキストは、指定されたキャンバス サイズである必要があります。サービスは 10 秒ごとにコードを実行し、それよりも時間がかかる場合は最大 2 つのスレッドを使用します。私は TaskFactory を使用しています (指定したスレッドの量に制限するために LimitedConcurrencyLevelTaskScheduler をオーバーライドしました)。
これはうまく機能しますが、数日後 (長さは可変)、次の例外が発生し始めます。TPL を使用してマルチスレッド化する前は、同じコードが正常に機能していました。
これが何によって引き起こされているのかを理解する助けが必要です。私が調べているいくつかの考えは次のとおりです: TTF ファイルに保持されているスレッドの衝突、メモリの問題、ディスパッチャ (スタック トレースを参照) が TaskFactory とうまく連携していない、その他?? プロファイリングのセットアップは適切ではありませんが、例外が発生しているときにタスク マネージャーを調べたところ、メモリ使用量は正常に見えました。私の次の試みは、TextBlock オブジェクトを使用して、例外が回避されるかどうかを確認することです。
エラー メッセージ: 指定されたファイルが見つかりません エラー ソース: WindowsBase エラー ターゲット サイト: UInt16 RegisterClassEx(WNDCLASSEX_D)
例外スタック トレース:
MS.Win32.UnsafeNativeMethods.RegisterClassEx(WNDCLASSEX_D wc_d) で MS.Win32.HwndWrapper..ctor(Int32 classStyle、Int32 スタイル、Int32 exStyle、Int32 x、Int32 y、Int32 幅、Int32 高さ、文字列名、IntPtr 親、HwndWrapperHook [] フック) で System.Windows.Threading.Dispatcher..ctor() で System.Windows.Threading.Dispatcher.get_CurrentDispatcher() で System.Windows.Media.TextFormatting.TextFormatter.FromCurrentDispatcher(TextFormattingMode textFormattingMode) で System.Windows. Media.FormattedText.LineEnumerator..ctor(FormattedText text) で System.Windows.Media.FormattedText.DrawAndCalculateMetrics(DrawingContext dc, Point drawingOffset, Boolean getBlackBoxMetrics) で System.Windows.Media.FormattedText.get_Metrics() で (ループ内の FormattedText)
private static Size GetTextSize(string txt, Typeface tf, int size)
{
FormattedText ft = new FormattedText(txt, new CultureInfo("en-us"), System.Windows.FlowDirection.LeftToRight, tf, (double)size, System.Windows.Media.Brushes.Black, null, TextFormattingMode.Display);
return new Size { Width = ft.WidthIncludingTrailingWhitespace, Height = ft.Height };
}
編集:これまでのところ、この関数を呼び出すコードの周りにロックを配置し、次のように CurrentDispatcher.Invoke メソッド内で呼び出すことを試みました。
return (Size)Dispatcher.CurrentDispatcher.Invoke(new Func<Size>(() =>
{
FormattedText ft = new FormattedText(txt, new CultureInfo("en-us"), System.Windows.FlowDirection.LeftToRight, tf, (double)size, System.Windows.Media.Brushes.Black, null, TextFormattingMode.Display);
return new Size { Width = ft.WidthIncludingTrailingWhitespace, Height = ft.Height };
}));
編集: 他の人へのリンクを見つけましたが、正確な問題ではありません。 http://www.eggheadcafe.com/software/aspnet/31783898/problem-creating-an-bitmapsource-from-an-hbitmap-in-threaded-code.aspx ~同様の問題がありますが、回答はありません
System.Windows.Media.DrawingVisual.RenderOpen() しばらくするとエラーが発生します ~ 同様の問題がありますが、回答はありません
http://connect.microsoft.com/VisualStudio/feedback/details/361469/net-3-5-sp1-breaks-use-of-wpf-under-iis# ~ 同様の例外ですが、3.5SP1 は使用していませんまたはIIS 7。
Microsoft Connect サイトからもこれを送信しました (同様の問題が発生している場合は、投票してください)。 https://connect.microsoft.com/WPF/feedback/details/654208/wpf-formattedtext-the-system-cannot-find-the-file-specified-exception-in-a-service
編集: Microsoft からの応答:「WPF オブジェクトは、スレッド プール スレッドではなく、ディスパッチャー スレッドで作成する必要があります。通常は、スレッドを専用にして、ディスパッチャー ループを実行し、オブジェクトを作成してそれらを凍結して返す要求にサービスを提供することをお勧めします。ありがとう、WPF チーム」 〜これをどのように実装しますか?
EDIT:NightDwellerのおかげで最終的な解決策
if(Application.Current == null) new Application();
(Size)Application.Current.Dispatcher.CurrentDispatcher.Invoke(new Func<Size>(() =>
{
...});
編集: 変更 (new Application();) をデプロイすると、「同じ AppDomain に複数の System.Windows.Application インスタンスを作成できません」というエラーが記録されました。エラー ソース: PresentationFramework エラー ターゲット サイト: Void .ctor()