使用TPL将程序图标渲染到Image Control

时间:2011-10-07 09:10:14

标签: c# wpf behavior task-parallel-library

您好我正在尝试创建一个Interactivity.Behavior来在后台加载程序的图标。以下是代码,但它给了我调用线程无法访问此对象,因为不同的线程拥有它..

protected override void OnAttached()
    {
        base.OnAttached();

        if (!string.IsNullOrEmpty(Url))
        {
            Icon ico = Icon.ExtractAssociatedIcon(Url);
            if (ico != null)
            {

               taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
                Task.Factory.StartNew(() => {
                                                MemoryStream ms = new MemoryStream();
                                                ico.ToBitmap().Save(ms, ImageFormat.Png);
                                                ms.Position = 0;
                                                BitmapImage bi = new BitmapImage();
                                                bi.BeginInit();
                                                bi.StreamSource = ms;
                                                bi.EndInit();
                                                return bi;
                                            }).ContinueWith((t) => AssociatedObject.Source = t.Result, taskScheduler);




            }

        }
    }

2 个答案:

答案 0 :(得分:0)

虽然您正在使用CurrentSynchronizationContext,但如果可能必须在图标的Dispatcher上运行,请尝试使用它。

    ico.Dispatcher.BeginInvoke(
         new Action(
           () =>
           {
              ico.ToBitmap().Save(ms, ImageFormat.Png); 
              ///rest of the code that uses `ms`.
           }));

建议:为什么不使用Priority BindingBinding.IsAsync来缓慢加载图片....

http://social.msdn.microsoft.com/Forums/en-AU/wpf/thread/b3dc9baa-4cf6-49ed-a316-b9fb1cd29516

答案 1 :(得分:0)

WPF对象(从DispatcherObject下降的任何东西)是线程仿射的 - 通常它们只能在创建它们的线程上使用。这包括BitmapImage个对象。如果在后台线程上创建BitmapImage,那么它只能在该后台线程中使用 - 这意味着UI线程在尝试显示位图时会出错。

然而,BitmapImage来自Freezable。 Freezable有一个Freeze方法,可以使实例为只读。根据MSDN上的“Freezable Objects Overview”:

  

冻结的Freezable也可以在线程之间共享,而解冻的Freezable则不能。[/ p>

因此,如果您在从后台任务返回图像之前添加对bi.Freeze();的调用,那么您应该能够从UI线程成功使用该图像。