我的应用程序运行CPU密集的algorythms来编辑放置在WPF窗口的图像.我需要在后台线程中完成编辑.但是,尝试在非UI线程中编辑WritableBitmap的BackBuffer会引发InvalidOperationException.
private WriteableBitmap writeableBitmap;
private void button1_Click(object sender, RoutedEventArgs e)
{
// Create WritableBitmap in UI thread.
this.writeableBitmap = new WriteableBitmap(10, 10, 96, 96, PixelFormats.Bgr24, null);
this.image1.Source = this.writeableBitmap;
// Run code in non UI thread.
new Thread(
() =>
{
// 'Edit' bitmap in non UI thread.
this.writeableBitmap.Lock(); // Exception: The calling thread cannot access this object because a different thread owns it.
// ... At this place the CPU is highly loaded, we edit this.writeableBitmap.BackBuffer.
this.writeableBitmap.Unlock();
}).Start();
}
Run Code Online (Sandbox Code Playgroud)
我已阅读了几十本手册,所有这些手册都告诉我在UI线程(即MSDN)中执行BackBuffer版本.
如何在非UI线程中编辑WritableBitmap.BackBuffer而不进行任何无用的缓冲区复制/克隆?
LOA*_*OAS 11
MSDN建议在后台线程中写入后备缓冲区.只需要在UI线程上执行某些更新前和更新后操作.因此,当后台线程正在进行实际更新时,UI线程可以自由地执行其他操作:
//Put this code in a method that is called from the background thread
long pBackBuffer = 0, backBufferStride = 0;
Application.Current.Dispatcher.Invoke(() =>
{//lock bitmap in ui thread
_bitmap.Lock();
pBackBuffer = (long)_bitmap.BackBuffer;//Make pointer available to background thread
backBufferStride = Bitmap.BackBufferStride;
});
//Back to the worker thread
unsafe
{
//Carry out updates to the backbuffer here
foreach (var update in updates)
{
long bufferWithOffset = pBackBuffer + GetBufferOffset(update.X, update.Y, backBufferStride);
*((int*)bufferWithOffset) = update.Color;
}
}
Application.Current.Dispatcher.Invoke(() =>
{//UI thread does post update operations
_bitmap.AddDirtyRect(new System.Windows.Int32Rect(0, 0, width, height));
_bitmap.Unlock();
});
Run Code Online (Sandbox Code Playgroud)