屈服并释放内存
我有 WCF Web 服务,用于将图像从 Windows Mobile 客户端应用程序发送到我的服务器。
当我尝试发送图像时,我无法同时从数据库加载所有图像,否则会出现内存不足异常。所以我想我会调用我的网络服务,批量为 10 个左右。
我想知道的是,如果我设置一个 IEnumerable
并一次从数据库 1 中yield
图像,那么在每批发送后,内存会被释放吗?
我知道依靠垃圾收集器来快速清理通常是一个坏主意。所以我很犹豫是否要这样做(这也是我问的原因)。
我能看到的唯一其他选项是调用数据库以获取 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 个项目批次存储在内存中,还是会同时全部存储在内存中?
I have WCF web service that I use to send images from my Windows Mobile client app to my server.
When I try to send the images I can't load all of them from my database at the same time or I will get an out of memory exception. So I am thinking I will call my web service with batches of 10 or so.
What I want to know is, if I set up an IEnumerable
and yield
the images from the database 1 at a time, will the memory be freed after each batch is sent?
I know relying on the Garbage Collector for speedy cleanup is usually a bad idea. So I am hesitant do do this (and hence the reason I am asking).
The only other option I can see is to make a call to the database to get the data in sets of 10 (seems inelegant, but I may have to do that).
Let me summarize with an example. Say I have the following code. When will the item returned by the yield (MyYieldingEnumerable) have its memory free (or at least available for garbage collection)?
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
Will they be in memory in 10 item batches or will they all end up in memory at the same time?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这取决于您的代码在
MyYieldingEnumerable
中执行的操作以及如何创建boxes
列表。itemsToSend
列表除非通过myService.SendItems
调用保持活动状态,否则将不会被引用,因此 GC 可以回收它。但缺少太多代码,无法给出结论。但真正的问题不是这段代码,而是你处理文件传输的整体方法。将整个文件加载到内存中并将它们传递给 WCF 代理在现实生活中是行不通的。仅一个文件就可能大到足以毁掉您的应用程序,因此批处理 10 不会节省任何时间。您需要实现清晰的端到端流语义:从客户端上以块的形式读取文件,以块的形式发送文件,以及以块的形式将其写入目的地。如果这些文件传输操作是应用程序的主要部分,那么恢复(能够从某个偏移量恢复文件传输)也许公平性(一个大文件不会中断所有其他文件)也可能是要求。
我建议您在 MSDN 中查看此主题:WCF 如何:启用流式处理。
It depends on what your code does in
MyYieldingEnumerable
and how is theboxes
list created. TheitemsToSend
list, unless kept alive by themyService.SendItems
call, will be unreferenced and therefore GC could reclaim it. But there is just too much code missing to give a verdict.But the real problem is not this code, is in your overall approach in handling file transfer(s). Loading entire file(s) in memory and passing them to WCF proxies is just not going to work in real life. One single file alone can be large enough to ruin your application, so batching 10 saves nothing. You need to implement clear streaming semantics, end-to-end: from reading file on client in chunks, sending it in chunks, and writing it at destination in chunks. If these file transfer operations are the bread and butter of the app then resume (be able to resume a file transfer from a certain offset) and perhaps fairness (one big file does not interrupt every other file(s)) are likely also requirements.
I suggest you go over this topic in MSDN: WCF How to: Enable Streaming.