自定义磁贴在wp8中生成System.OutOfMemoryException异常

时间:2014-08-07 05:10:14

标签: c# .net windows-phone-8

有没有人知道为什么我在创建自定义磁贴时遇到OutOfMemoryException?

我尝试在ScheduledAgent的Windows Phone 8应用上为我的主要磁贴创建自定义图像。在执行NotifyComplete()的最后一行代码之前,错误不会发生。

这是代码(不是最干净但我认为可以用于原型设计)。此代码仅处理宽磁贴,并尝试将图像加载从网站下载的图像,然后尝试在此图像上呈现徽标和描述。

以下是代码:

    private void CreateTiles()
    {
        Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            for (int i = 0; i < 2; i++)
            {
                var bmp = new WriteableBitmap(691, 336);
                var articleImg = new BitmapImage(new Uri(articles[i].ImageFilename, UriKind.Relative));
                var articleImage = new Image { Source = articleImg };
                articleImage.Stretch = Stretch.UniformToFill;
                articleImg.CreateOptions = BitmapCreateOptions.None; // Force the bitmapimage to load it's properties so the transform will work

                var bmpLogo = new WriteableBitmap(100, 100);
                var logoImg = new BitmapImage(new Uri("/Assets/Tiles/FlipCycleTileSmall.png", UriKind.Relative));
                var logoImage = new Image { Source = logoImg };
                logoImage.Opacity = 1.0;
                logoImg.CreateOptions = BitmapCreateOptions.None; // Force the bitmapimage to load it's properties so the transform will work

                var articleBannerGrid = new Grid();
                articleBannerGrid.Background = ColorExtensions.ToSolidColorBrush("#000F558E");
                articleBannerGrid.Opacity = .5;
                articleBannerGrid.Height = 100;
                articleBannerGrid.VerticalAlignment = VerticalAlignment.Bottom;
                articleBannerGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(100) });
                articleBannerGrid.ColumnDefinitions.Add(new ColumnDefinition());
                articleBannerGrid.Children.Add(logoImage);

                Grid.SetColumn(logoImage, 0);

                var textBlock = new TextBlock();
                textBlock.Text = articles[i].Description;
                textBlock.FontWeight = FontWeights.Bold;
                textBlock.Margin = new Thickness(10, 5, 30, 5);
                textBlock.TextWrapping = TextWrapping.Wrap;
                textBlock.Foreground = new SolidColorBrush(Colors.White); //color of the text on the Tile
                textBlock.FontSize = 30;
                textBlock.Opacity = 1.0;

                var articleTextGrid = new Grid();
                articleTextGrid.Height = 100;
                articleTextGrid.VerticalAlignment = VerticalAlignment.Bottom;
                articleTextGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(100) });
                articleTextGrid.ColumnDefinitions.Add(new ColumnDefinition());
                articleTextGrid.Children.Add(textBlock);

                Grid.SetColumn(textBlock, 1);

                var canvas = new Grid();
                canvas.Width = articleImg.PixelWidth;
                canvas.Height = articleImg.PixelHeight;
                canvas.Children.Add(articleImage);
                canvas.Children.Add(articleBannerGrid);
                canvas.Children.Add(articleTextGrid);

                bmp.Render(canvas, null);
                bmp.Invalidate(); //Draw bitmap

                FileStream fs = new FileStream(articles[i].ImageFilename, FileMode.Create);
                bmp.SaveJpeg(fs, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
                fs.Close();
                fs.Dispose();
                articleImage = null;
                articleImg = null;
            }

            //GC.Collect();
            //GC.WaitForPendingFinalizers();

            ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault();

            if (TileToFind != null)
            {
                string title = articles[0].Tag;
                string backTitle = articles[1].Tag;
                string content = articles[0].Description;
                string backContent = articles[1].Description;

                FlipTileData tileData = new FlipTileData()
                {
                    Title = title,
                    BackTitle = backTitle,
                    BackContent = backContent,
                    WideBackContent = backContent,
                    BackgroundImage = new Uri(articles[0].ImageFilename, UriKind.Relative),
                    BackBackgroundImage = new Uri(articles[1].ImageFilename, UriKind.Relative),
                    WideBackgroundImage = new Uri(articles[0].ImageFilename, UriKind.Relative),
                    WideBackBackgroundImage = new Uri(articles[1].ImageFilename, UriKind.Relative),
                };

                TileToFind.Update(tileData);
            }

            NotifyComplete();

        });
    }

我认为它是生成自定义磁贴的正确位置,即ScheduledAgent。

我在诺基亚网站上发现了一篇文章Dynamic Live Tile issue WP8 [WriteableBitmap]但问题相同,但也没有解决方案。

我明天将继续调试,删除所有内容并逐步添加每个位,看看我是否能发现任何内容,但如果有人有任何建议或解决方案,我很感激您是否可以提供帮助

如果我以错误的方式处理它,请告诉我在预定代理中更新磁贴的最佳方法。

感谢。

2 个答案:

答案 0 :(得分:2)

WP BackgroundAgents的内存上限很小。没有更新3的WP8为20MB,更新3的WP8为25。

我建议您创建另一个项目并将Coding4Fun工具包和MemoryCounter添加到您的网页中,然后将BackgroudAgent中的代码添加到示例页面并尝试创建瓷砖。然后看看它使用了多少内存。我认为内存使用量高于20 / 25MB上限。如果是这样,你必须找到减少它的方法。

答案 1 :(得分:0)

像往常一样,微软正在从其文档中省略重要信息。

将我的磁贴的大小从691x336缩小到336x165后,它运行起来,所以它让我思考,我认为微软在本文Flip Tile template for Windows Phone 8中为wp8和wp8.1推荐的大小似乎过大,所以我做了一些研究,这是我在stackoverflow中的一篇文章中找到这个优秀的解释,即

Windows Phone 8 Startscreen Tile sizes and margins

这清楚地说明了瓷砖的大小,但不是基于操作系统版本,而是基于屏幕分辨率。

在我的测试环境中,我使用的是默认的模拟器WVGA 512MB&#39;并且默认情况下屏幕尺寸为480x800,因此考虑到本文答案中提供的信息,我的图块尺寸应为430x210。

我将我(已经缩小的)磁贴重新调整为430x210,它仍然可以工作。

虽然内存上限为20 / 25Mb,具体取决于使用的操作系统和补丁程序,这可能会导致我在网上阅读的各篇文章出现许多问题,在我的实例中我认为更有可能已经受到瓷砖尺寸不正确的影响,因此影响了额外的记忆或缺乏记忆。

一旦我在IDE中使用8.1并且分辨率更高,我将更新这篇文章但是现在,我必须假设它肯定与我的磁贴的大小有关。

我绝对要确保根据所使用的操作系统,补丁和分辨率添加代码来创建磁贴。最诚实的一点痛苦!

希望这会有所帮助。