2011-10-07 82 views
0

嗨,我試圖創建一個Interactivity.Behavior在後臺加載程序的圖標。以下是代碼,但它給我的調用線程,因爲不同的線程擁有它無法訪問該對象..使用TPL將圖像控件呈現給圖像控件

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); 




      } 

     } 
    } 

回答

0

WPF對象(任何從DispatcherObject下降的東西)都是線程仿射的 - 通常它們只能在創建它們的線程上使用。這包括BitmapImage對象。如果您在後臺線程上創建BitmapImage,那麼只能從後臺線程使用 - 這意味着UI線程在嘗試顯示位圖時會出現錯誤。

但是,BitmapImage從Freezable下降。 Freezable有一個Freeze方法將使實例只讀。並根據MSDN上的「Freezable Objects Overview」:

凍結的Freezable也可以跨線程共享,而解凍的Freezable則不能。

因此,如果您在從後臺任務返回圖像之前添加對bi.Freeze();的調用,那麼您應該能夠從UI線程成功使用該圖像。

+0

THanks ..我今天學到了一些新東西...;) 但是...我試着將AssociatedObject.Source = bi放在Task的Action委託中,並使用Task.Factory.StartNew(()=> .. ..,CancellationToken.None,TaskCreationOptions.None,taskScheduler);它的工作原理也是......有什麼區別? – icube

+0

如果使用'TaskScheduler.FromCurrentSynchronizationContext'啓動任務,則在當前線程中運行它。你完全可以不使用任務。 –