Hi i’m trying to create an Interactivity.Behavior to load a program’s icon in the background. The following is the code but it gave me The calling thread cannot access this object because a different thread owns it..
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);
}
}
}
WPF objects (anything that descends from DispatcherObject) are thread-affine — normally they can only be used on the thread that created them. This includes BitmapImage objects. If you create the BitmapImage on a background thread, then it can only be used from that background thread — which means that the UI thread will get an error when it tries to display the bitmap.
However, BitmapImage descends from Freezable. Freezable has a Freeze method that will make the instance read-only. And per the “Freezable Objects Overview” on MSDN:
So if you add a call to
bi.Freeze();just before you return the image from your background task, then you should be able to use the image successfully from your UI thread.