我们正在使用 WPF FormattedText 对象来确定从 RSS 提要中获取最新新闻标题的服务中的文本大小。检索到的文本需要采用指定的画布大小。该服务每 10 秒运行一次代码,如果一个线程需要更长的时间,则最多使用 2 个线程。我正在使用 TaskFactory(我已经覆盖了 LimitedConcurrencyLevelTaskScheduler 以限制我指定的线程数量)。
这很好用,除了几天后(长度可变),我们开始得到以下异常。在我们开始使用 TPL 使其成为多线程之前,相同的代码运行良好。
我需要帮助找出这是由什么引起的。我正在研究的一些想法是:保留 TTF 文件的线程冲突、内存问题、调度程序(参见堆栈跟踪)不能很好地与 TaskFactory 配合使用,其他?我们没有很好的分析设置,但是当异常发生并且内存使用看起来正常时,我们已经查看了 TaskManager。我的下一个尝试是使用 TextBlock 对象并查看是否避免了异常。
错误信息:系统找不到指定的文件错误源:WindowsBase 错误目标站点:UInt16 RegisterClassEx(WNDCLASSEX_D)
异常堆栈跟踪:
在 MS.Win32.UnsafeNativeMethods.RegisterClassEx(WNDCLASSEX_D wc_d) 在 MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook [] 钩子)在 System.Windows.Threading.Dispatcher.get_CurrentDispatcher() 在 System.Windows.Media.TextFormatting.TextFormatter.FromCurrentDispatcher(TextFormattingMode textFormattingMode) 在 System.Windows 的 System.Windows.Threading.Dispatcher..ctor()。 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 (我的方法使用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 对象需要在 Dispatcher 线程上创建,而不是线程池线程。我们通常建议使用一个线程来运行 Dispatcher 循环来服务请求以创建对象并将它们冻结返回。谢谢,WPF 团队” 〜我将如何实现这个?
编辑:感谢 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()