产量和释放记忆

时间:2010-10-22 23:18:28

标签: c# memory-management yield

我有WCF网络服务,用于将图像从我的Windows Mobile客户端应用程序发送到我的服务器。

当我尝试发送图像时,我无法同时从我的数据库中加载所有图像,否则我将获得内存不足异常。所以我想我将以10个左右的批次调用我的Web服务。

我想知道的是,如果我一次设置IEnumerableyield来自数据库1的图像,是否会在发送每个批次后释放内存?

我知道依靠垃圾收集器进行快速清理通常是个坏主意。所以我犹豫不决(因此我要问的原因)。

我能看到的唯一另一个选择是调用数据库来获取10组数据(看起来不太优雅,但我可能不得不这样做。)

让我用一个例子来总结一下。说我有以下代码。 yield(MyYieldingEnumerable)返回的项目何时可以释放内存(或至少可用于垃圾回收)?

public void SendImages()
{
    List<ImageItem> itemsToSend = new List<ImageItem>();
    int count = 0;
    foreach (ImageItem curImageItem in MyYieldingEnumerable())
    {
        itemsToSend.Add(curImageItem);
        count++;
        if (count >= 10)
        {
            myService.SendItems(itemsToSend);

            // #1 When the last reference to it is removed
            //     |
            //     v
            itemsToSend = new List<ImageItem>();
            count = 0;
        }
    }
    // <----- #2 After the loop ends
}
// <------- #3 After the method exits

他们是否会在10个项目的内存中存在,或者它们是否会同时存在于内存中?

1 个答案:

答案 0 :(得分:4)

这取决于您的代码在MyYieldingEnumerable中执行的操作以及boxes列表的创建方式。 itemsToSend列表除非被myService.SendItems调用保持活动,否则将被取消引用,因此GC可以回收它。但是,有太多的代码缺少判决。

但真正的问题不是这个代码,而是处理文件传输的整体方法。将整个文件加载到内存中并将它们传递给WCF代理只是在现实生活中无法运行。单独一个文件可能足以破坏您的应用程序,因此批处理10不会保存任何内容。您需要实现端到端的清晰流式语义:从客户端以块的形式读取文件,以块的形式发送它,以及以块的形式将其写入目标。如果这些文件传输操作是应用程序的面包和黄油然后恢复(能够从某个偏移恢复文件传输)并且可能公平性(一个大文件不会中断每个其他文件)也可能是要求。

我建议您在MSDN中查看此主题:WCF How to: Enable Streaming