views:

79

answers:

1

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?

+3  A: 

It depends on what your code does in MyYieldingEnumerable and how is the boxes list created. The itemsToSend list, unless kept alive by the myService.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.

Remus Rusanu
Thank you for the response. I looked into streaming. I asked if it would help my scenario here: http://stackoverflow.com/questions/3999842/does-streaming-a-wcf-soap-help-the-client-send-using-less-memory The answer I got indicated streaming would not help me. As for the missing code, most of it has not been written. I could make be however would work best. The files I am sending are a known size (they are screenshots that my application created). NOTE: `Boxes` was a leftover from the code I used to make this example. As I see it, this sample method should have had no parameters.
Vaccano
I will double check, but I'm pretty sure the answer you got on your streaming question is just plain wrong.
Remus Rusanu