Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>WriteableBitmap needs be called from the UI thread. It's just a limitation in that utility you can't get around.</p> <p>From MSDN:</p> <blockquote> <p>The WriteableBitmap class uses two buffers. The back buffer is allocated in system memory and accumulates content that is not currently displayed. The front buffer is allocated in system memory and contains the content that is currently displayed. The rendering system copies the front buffer to video memory for display. </p> <p>Two threads use these buffers. The user interface (UI) thread generates the UI but does not present it to the screen. The UI thread responds to user input, timers, and other events. An application can have multiple UI threads. The render thread composes and renders changes from the UI thread. There is only one render thread per application.</p> <p>The UI thread writes content to the back buffer. The render thread reads content from the front buffer and copies it to video memory. Changes to the back buffer are tracked with changed rectangular regions.</p> </blockquote> <p><a href="http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap.aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap.aspx</a></p> <p><strong>Alternative to BackgroundWorker:</strong></p> <p>There is no getting around the fact you need to do this on the UI thread. But you can push it to the end of the queue so that it might be less noticable to the user.</p> <p>Try something like this:</p> <pre><code>public static void RunDelayedOnUiThread(Action action) { Deployment.Current.Dispatcher.BeginInvoke(() =&gt; { var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(1) }; timer.Tick += (sender, args) =&gt; { timer.Stop(); action(); }; timer.Start(); }); } </code></pre> <p>This should be enough so that your image processing (in this case the action that is passed) will be put at the end of the queue that is waiting to be processed on the UI thread. Your image processing will still block the UI thread while it is working, but at least everything else should be done first. </p> <p>How it works:</p> <p>When you call BeginInvoke, your action is placed at the end of the dispatcher's queue, to be run when the UI thread is freed up from what it is currently doing (running your code). But because you could call BeginInvoke again (and again and again) and then your image processing would block the other things in the dispatcher's queue, we want to put it at the back again. This is where the DispatcherTimer comes in. From MSDN:</p> <blockquote> <p>Timers are not guaranteed to execute exactly when the time interval occurs, but they are guaranteed to not execute before the time interval occurs. This is because DispatcherTimer operations are placed on the Dispatcher queue like other operations. When the DispatcherTimer operation executes is dependent on the other jobs in the queue and their priorities.</p> </blockquote> <p>So just the one millisecond interval we give it should be enough to shove this right back to the end of the queue.</p> <p>On Windows Phone 7, this may still block some touch events, but at least you won't have blocked your page from rendering.</p> <p>On Windows Phone 8, the Panorama, Pivot, and LongListSelector all respond to input on a non UI thread, so you would be a little safer there.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload