I have a situation where I need to display a very large bitmap using smaller "tiles". The contents of the tiles can change, so I was going to use WriteableBitmap until I ran into its numerous threading restrictions. I want to modify the tiles from a background thread, so that the smooth scrolling and zooming is not affected.
I guess I am not understanding WriteableBitmap, or maybe it is intended for strictly different use cases than what I require. Specifically, the threading issues I ran into are:
- You can't Lock or Unlock the bitmap from a different thread, as you will get an InvalidOperationException. You need to call Invoke on the the bitmap's dispatcher object for the Lock/Unlock calls. Which means the background thread will block until the UI thread gets around to unlocking/locking it.
- While the bitmap is locked, the render thread will block. Which kinda defeats the purpose of using background threads in this case since how long it is locked affects the UI.
- You can't even get the PixelWidth or PixelHeight from a background thread without getting an InvalidOperationException. These are read-only properties, so I fail to see the restriction in that case. So you need to create a wrapper class around WriteableBitmap (can't derive from WriteableBitmap) just to host mirror values of these properties.
At which point you might as well just create your own implementation of WriteableBitmap, which is what I did. Basically:
- Any thread can call Lock/Unlock without restriction. Once locked, any thread can get the back buffer.
- Any thread can set a paramenter in the Unlock call indicating that the contents has changed.
- During Unlock, if the lock count goes to zero, and any thread set the changed parameter to true indicating that changes were made to the back buffer, the thread creates a new bitmap from the back buffer using BitmapSource.Create, and then calls Freeze on the bitmap so that it can be used by any other thread, including the render thread. The previous bitmap is then swapped with the newly created one. There is zero overhead to the UI thread in this scenario.
So I guess my point is that I want to understand the purpose of WriteableBitmap, since it is essentially useless for my requirement. Did I just completely miss the point with it? Maybe it works well in a stream decoder scenario or something...?