这个问题已经在这里有了答案 :
调用线程无法访问该对象,因为其他线程拥有它 (13个答案)
5年前关闭。
为什么我无法在以下代码中创建CroppedBitmap?我有一个例外:
调用线程无法访问该对象,因为其他线程拥有它。
如果我将代码更改为
CroppedBitmap cb = new CroppedBitmap(new WriteableBitmap(bf), new Int32Rect(1, 1, 5, 5));
例外不见了?为什么呢?
代码1,位于的异常cb.Freeze():
cb.Freeze()
public MainWindow() { InitializeComponent(); ThreadPool.QueueUserWorkItem((o) => { //load a large image file var bf = BitmapFrame.Create( new Uri("D:\\1172735642.jpg"), BitmapCreateOptions.None, BitmapCacheOption.None); bf.Freeze(); Dispatcher.BeginInvoke( new Action(() => { CroppedBitmap cb = new CroppedBitmap(bf, new Int32Rect(1,1,5,5)); cb.Freeze(); //set Image's source to cb.... }), DispatcherPriority.ApplicationIdle); } ); }
代码2的工作原理:
ThreadPool.QueueUserWorkItem((o) => { var bf = BitmapFrame.Create( new Uri("D:\\1172740755.jpg"), BitmapCreateOptions.None, //BitmapCreateOptions.DelayCreation, BitmapCacheOption.None); bf.Freeze(); var wb = new WriteableBitmap(bf); wb.Freeze(); this.Dispatcher.Invoke( new Action(() => { var r = new Int32Rect(1, 1, 5, 5); CroppedBitmap cb = new CroppedBitmap(wb, r); cb.Freeze(); //set Image's source to cb.... Image.Source = cb; }), DispatcherPriority.ApplicationIdle); } );
代码3,无需WritableBitmap即可工作:
ThreadPool.QueueUserWorkItem((o) => { var bf = BitmapFrame.Create( new Uri("D:\\1172735642.jpg"), BitmapCreateOptions.None, //BitmapCreateOptions.DelayCreation, BitmapCacheOption.None); bf.Freeze(); var bf2 = BitmapFrame.Create(bf); bf2.Freeze(); this.Dispatcher.Invoke( new Action(() => { var r = new Int32Rect(1, 1, 5, 5); BitmapSource cb = new CroppedBitmap(bf2, r); cb.Freeze(); //set Image's source to cb.... Image.Source = cb; }), DispatcherPriority.ApplicationIdle); } );
您可以在反射器中浏览此类。cb.Freeze()中会出现异常。在
CroppedBitmap cb = new CroppedBitmap(bf, new Int32Rect(1,1,5,5));
案例构造函数做了这样的事情:
this.this.Source = source;
因此源不是在当前线程中创建的,因此异常会上升。在
new WriteableBitmap(bf)
在这种情况下,构造函数与bf对象同步,并且在当前线程中创建了新的源,因此不会出现异常。如果您对深度细节感兴趣,可以随时使用Reflector反映基本库:)