1

I have a background task that should run every N (doesn't matter) minutes to create a UI control and render it to image and save it Pictures Library. I wrote some code here:

public async void Run(IBackgroundTaskInstance taskInstance)
    {
        var def = taskInstance.GetDeferral();

        // creating control
        var canvas = new Canvas
        {
            Height = 100,
            Width = 100
        };

        canvas.Children.Add(new TextBlock { Text = "Hello world" });

        var size = new Size(100, 100);

        canvas.Measure(size);
        canvas.UpdateLayout();
        canvas.Arrange(new Rect(0, 0, size.Width, size.Height));

        // rendering
        var bitmap = new RenderTargetBitmap();
        await bitmap.RenderAsync(canvas);

        // saving as jpg
        var file = await KnownFolders.PicturesLibrary.CreateFileAsync("sample.jpg");
        using (var stream = await file.OpenStreamForWriteAsync())
        {
            var pixelBuffer = await bitmap.GetPixelsAsync();
            var logicalDpi = DisplayInformation.GetForCurrentView().LogicalDpi;

            // convert stream to IRandomAccessStream
            var randomAccessStream = stream.AsRandomAccessStream();

            // encoding & finish saving
            var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, randomAccessStream);
            encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)bitmap.PixelWidth,
                                 (uint)bitmap.PixelHeight, logicalDpi, logicalDpi, pixelBuffer.ToArray());

            await encoder.FlushAsync();
        }

        def.Complete();
    }

But i've got 2 problems here.

  1. We can't create UI element in background, only in UI Thread. Is there any possible way to create it from background task? I've tried many ways to use dispatchers but this didn't work...

  2. Following to this article and this question we can't render an image from control that is not in visual tree of current page. Is there any possible hack of this thing?

Thanks for any help

Community
  • 1
  • 1
winnie1pooh
  • 13
  • 1
  • 4
  • I've used DispatcherTimer to perform similar tasks in the past without any issues. What type of issues did you have using a dispatcher? – Daniel Oct 03 '13 at 20:05
  • Doc, what exactly should i write to make this code working? I tried this: await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => { // do job here }); i get InvalidOperationException when access to MainWindow with message "A method was called at an unexpected time. (Exception from HRESULT: 0x8000000E)" and so on. How do i need access dispatcher in right way? – winnie1pooh Oct 03 '13 at 21:10
  • 1
    @AMR- Spy software? A Win 8 App Store application could only capture an image of its own contents -- which means it already had access to all of the data on the screen anyway. – WiredPrairie Oct 03 '13 at 21:13
  • I am happy to report that this is no longer the case with Windows Phone 8.1 - you can render in the background now. – Jerry Nixon May 13 '14 at 15:14
  • Hi all, I'm getting the same issue rendering XAML elements to bitmap in WinRT "A method was called at an unexpected time". The element is in the visual tree. Is this ever going to be supported? It kind of hamstrings our attempts to port a high speed charting library (www.scichart.com) over to WinRT, as we depend on RenderToBitmap to render sprites ( markers, scatter charts). Works great in WPF/SL! ... – Dr. Andrew Burnett-Thompson Feb 10 '15 at 11:44

1 Answers1

0

I'm asking some related question in MSDN forum. My repro code may help you. In repro code I create CoreApplicationView as background UI thread,then call RenderAsync to generate image for target UIElement. This repro code has some problem for me ,but it may work fine for you.

My question is here

Masahiko Miyasaka
  • 171
  • 1
  • 1
  • 11