【问题标题】:Scheduled Agent memory leak计划代理内存泄漏
【发布时间】:2013-03-21 00:38:55
【问题描述】:

大家好,我的 WP8 应用程序的 ScheduledAgent 出现内存泄漏问题。我正在尝试做的是循环更新应用程序的多个图块,看起来还可以(就内存使用而言),但由于某种原因,更新图块后内存没有释放。

我的代码如下所示(Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage 测量的内存使用情况):

protected override void OnInvoke(ScheduledTask task)
{
    try
    {
        Deployment.Current.Dispatcher.BeginInvoke(() =>
         {
             // 5MB used
             foreach (int id in myIdsList)
                UpdateTile(id);
         });
    }
    catch (Exception e)
    {
        if (Debugger.IsAttached)
            Debugger.Break();
    }

    NotifyComplete();
}

更新方法如下:

public void UpdateTile(int id)
{
    MyClass myClassInstance = GetInstanceById(id);

    //~6MB used by now

    Canvas drawingSurface = new Canvas();

    //Add some Image objects to canvas (source to each image is a filePath 
    // contained in myClassInstance)
    //~7MB

    WriteableBitmap bigTileImage = new WriteableBitmap(691, 336);
    bigTileImage.Render(drawingSurface, null);
    bigTileImage.Invalidate();

    //~9MB

    var bigTilePath = string.Format(/*path here*/);

    using (IsolatedStorageFile storage = 
           IsolatedStorageFile.GetUserStoreForApplication())
    {
        if (storage.FileExists(bigTilePath))
            storage.DeleteFile(bigTilePath);

        using (var isoFileStream = new IsolatedStorageFileStream(
            bigTilePath, FileMode.Create, storage))
        {
            bigTileImage.SaveJpeg(isoFileStream, bigTileImage.PixelWidth,
                                  bigTileImage.PixelHeight, 0, 100);
        }
    }

    ShellTile tileToUpdate = ShellTile.ActiveTiles.FirstOrDefault(
        x => x.NavigationUri.ToString().Contains("TileID="+id));
    FlipTileData flipTileData = new FlipTileData()
    {
        //Set fields
        WideBackgroundImage = 
            new Uri(("isostore:/"+bigTilePath, UriKind.Absolute),
    };

    tileToUpdate.Update(flipTileData);

    //~10MB used
    //Shouldn't memory be released by now??
    // calling GC.Collect() has no effect
}

所以,它是一个 PeriodicTask,我有 11MB 的内存上限,并且只要内存在迭代后没有释放,我就会得到 OutOfMemoryException。

也许我不了解基础知识,但我认为大部分占用的内存应该在将文件保存到 IS 后释放(或者每当 GC 决定收集时,但是,正如我所说,即使明确调用 GC.Collect() 也没有效果) ?

我做错了吗?有没有办法释放内存?

【问题讨论】:

  • 尝试使用像ANTS Memory Profiler 这样的内存分析器,看看你的假设是对还是错。
  • 你有没有试过在方法执行后调用GC.Collect()?也就是说,在 OnInvoke 中,在 UpdateTile() 之后调用 GC.Collect()。在方法结束时调用收集器不会生效,因为您仍然保留对所有对象的引用。
  • 你永远不会处理bigTileImage
  • @gjulianm,是的,我试过了 - 没有效果,记忆仍然没有释放
  • @leppie bigTileImage 是可写位图,不能隐式转换为'System.IDisposable';

标签: c# windows-phone-7 memory-leaks windows-phone-8 scheduled-tasks


【解决方案1】:

我不确定这是否是您的内存泄漏问题的唯一原因,但是;您正在创建一个 tile 对象,并且 1)您没有使用它 2)您也没有释放它。

ShellTile tileToipdate = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("TileID="+id));

这个 tileToipdate 对象有什么作用?查询后您没有使用它。如果没用,就把它去掉,看看会不会有什么改变。

如果你要使用这个对象,调用 tileToipdate.Finalize() 方法(在你完成之后),这里是mentioned,引用“允许一个对象尝试在垃圾回收器回收 Object 之前释放资源并执行其他清理操作。(继承自 Object。)"

希望对你有帮助。

【讨论】:

  • 对不起,我打错了(不是在真正的代码中,就在写这篇文章的时候)“tileToipdate”是“tileToUpdate”,它用于更新图块(tileToUpdate.Update(flipTileData);)。
  • 好吧,你仍然没有处理对象。
  • 不幸的是它不是一次性的,.Finalize() 方法是受保护的,所以不能从我的代码中调用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-08
  • 2015-06-14
相关资源
最近更新 更多