problem when using windows services

V

vishruth

This code works fine in Windows Application.
In Windows Application, I am able to zip the image files properly and it
totally contains 900MB
My problem is the same code which I used in my Windows Application,
does not work while I run it with Windows services.
In my Windows application I am able to zip the whole 900Mb without any
problems,
but in my windows services I am not able to zip the whole 900Mb.
In Windows Services it throws an error :SystemOutOfMemoryException
I am trying to zip all image files, example: idx,fim,rim
Below is the code I am using:

Please help me to find the solution to run this code properly in windows
services as well.

using Xceed.Compression;

using Xceed.FileSystem;

using Xceed.Zip;

Xceed.Zip.Licenser.LicenseKey = "ZINxx-xxxxx-xxxxx-xxxx";

public int MakeZipFile(string zipFileName, string[] filesToComp)
{
int retVal = 0;
DiskFolder tempFolder = new DiskFolder();
try
{
ZipArchive zip = new ZipArchive( new DiskFile( zipFileName ) );
zip.TempFolder = tempFolder;
try
{
zip.BeginUpdate();
foreach( string file in filesToComp )
{
DiskFile fileToZip = new DiskFile( file );
fileToZip.CopyTo( zip, true );
++retVal;
}
}
finally
{
zip.EndUpdate();
}
}

catch(Exception exec)
{
throw new ZipException(exec.Message);
}
finally
{
}
return retVal;
}
}

}

// Windows Services --- main part of execution

string zipfilepath="C:\\temp\\pollNew.zip"; // all my image files will be
zipped in pollnew.zip
string[] pFiles=new string[7]; // pFiles contains all files
that I want to zip
pFiles[0]="D:\\New\\121807\\00007069.FCI";
pFiles[1]="D:\\New\\121807\\00007069.FI2";
pFiles[2]="D:\\New\\121807\\00007069.FIM";
pFiles[3]="D:\\New\\121807\\00007069.IDX";
pFiles[4]="D:\\New\\121807\\00007069.RCI";
pFiles[5]="D:\\New\\121807\\00007069.RI2";
pFiles[6]="D:\\New\\121807\\00007069.RIM";
MakeZipFile(string zipfilepath, string[] pFiles) // calling MakeZipFile
Function Here
 
W

Willy Denoyette [MVP]

vishruth said:
This code works fine in Windows Application.
In Windows Application, I am able to zip the image files properly and it
totally contains 900MB
My problem is the same code which I used in my Windows Application,
does not work while I run it with Windows services.
In my Windows application I am able to zip the whole 900Mb without any
problems,
but in my windows services I am not able to zip the whole 900Mb.
In Windows Services it throws an error :SystemOutOfMemoryException
I am trying to zip all image files, example: idx,fim,rim
Below is the code I am using:

Please help me to find the solution to run this code properly in windows
services as well.

using Xceed.Compression;

using Xceed.FileSystem;

using Xceed.Zip;

Xceed.Zip.Licenser.LicenseKey = "ZINxx-xxxxx-xxxxx-xxxx";

public int MakeZipFile(string zipFileName, string[] filesToComp)
{
int retVal = 0;
DiskFolder tempFolder = new DiskFolder();
try
{
ZipArchive zip = new ZipArchive( new DiskFile( zipFileName ) );
zip.TempFolder = tempFolder;
try
{
zip.BeginUpdate();
foreach( string file in filesToComp )
{
DiskFile fileToZip = new DiskFile( file );
fileToZip.CopyTo( zip, true );
++retVal;
}
}
finally
{
zip.EndUpdate();
}
}

catch(Exception exec)
{
throw new ZipException(exec.Message);
}
finally
{
}
return retVal;
}
}

}

// Windows Services --- main part of execution

string zipfilepath="C:\\temp\\pollNew.zip"; // all my image files will
be
zipped in pollnew.zip
string[] pFiles=new string[7]; // pFiles contains all files
that I want to zip
pFiles[0]="D:\\New\\121807\\00007069.FCI";
pFiles[1]="D:\\New\\121807\\00007069.FI2";
pFiles[2]="D:\\New\\121807\\00007069.FIM";
pFiles[3]="D:\\New\\121807\\00007069.IDX";
pFiles[4]="D:\\New\\121807\\00007069.RCI";
pFiles[5]="D:\\New\\121807\\00007069.RI2";
pFiles[6]="D:\\New\\121807\\00007069.RIM";
MakeZipFile(string zipfilepath, string[] pFiles) // calling MakeZipFile
Function Here



Don't ever assume you have that huge block of free memory available in a
32-bit process. The fact that it works in a Windows program (say you were
lucky) doesn't mean it will work in another kind of application, note that
it's even possible that it will work all the time in your Windows
application one small change can easily spoil the party. If you need to make
sure that your memory demand as a chance to succeed, you'll have to
instantiate the MemoryFailPoint class from System.Runtime (assumes V2 of the
framework) before you initiate the memory consuming operation. Of course
this will need you to know the exact amount of memory needed for the
operation to succeed.
That said, I'm not entirely clear on why you need to run this from a Windows
Service, people tend to think that everything needs to run in the background
without even thinking about the complexities that come with developing
Services.

Willy.
 
V

vishruth

Thank you for your suggestion Willy, but at the same time, I am helpless,
that I have to run it only with windows services, as my company demands that.
Can u justify me that if the same code for zipping image files about 900mb
works with windows application,why doesnt it work with windows services.
But the same code in windows services works for lower MB files but if it
crosses say about 250 MB then I face this problem "System OutOfMemory
Exception".
If u can share your thoughts with me, I could pass on the same to the person
who assigned me this task.
It will be of gr8 help,then.

Thanks,
Vishruth
 
M

Marc Gravell

Is it possible that the zip library you are using is being
unnecessarily hungry here? I'm not familiar with the product (although
I recognise the name).

Off the wall, but have you tried the free but well-truested
sharpziplib? (and yes, I did notice that xceed sponsor icsharpcode).
(if you do, be sure to use a fixed size buffer; don't attempt to read
the entire source file at once).

Marc
 
W

Willy Denoyette [MVP]

vishruth said:
Thank you for your suggestion Willy, but at the same time, I am helpless,
that I have to run it only with windows services, as my company demands
that.
Can u justify me that if the same code for zipping image files about 900mb
works with windows application,why doesnt it work with windows services.
But the same code in windows services works for lower MB files but if it
crosses say about 250 MB then I face this problem "System OutOfMemory
Exception".
If u can share your thoughts with me, I could pass on the same to the
person
who assigned me this task.
It will be of gr8 help,then.


The reason it works in a Windows Forms (WF) application and not in a Windows
Service (WS) is because in the WF case you are lucky to find a huge block of
free memory to allocate from, while in the WS case, the process does not
have such a huge block available to allocate from.

This is mostly due to a difference in memory mapping, different modules
(managed and unmanaged DLL's) are mapped in the address space (2GB for a
32-bit process) of a WS process then those mapped in a WF application.
But again, this whole point is moot, the issue is that you (well the code)
are trying to allocate a *contiguous* block of memory which is larger then
the largest free region in the process space. The fact that it works now in
a WF application, doesn't mean it will work next time you start the process,
or that it will work all the time during the same run, memory space tends to
fragment while running code that allocates memory from the (native) heap and
from the ( LOH ) GC heap.
Also, a new release of the OS, the Framework, Third party code libraries....
can spoil the party because the base addresses of the modules loaded in the
process may change, the modules can increase in size or new modules can be
added to the Framework, resulting in an increased fragmentation.

Now, when it comes to WS, which are supposed to be highly available and
reliable, memory fragmentation becomes a real killer. That's why you should
try to prevent fragmentation (the GC does only prevent small object heap
fragmentation NOT LOH fragmentation) as much as possible, this by
allocating *as less* as possible, and/or by allocating *as small* as
possible.
You don't do that, because you have no idea about your memory requirements,
you simply assume that enough memory is available, note that the file sizes
you mention do not necessarily define the size of memory you need. The third
party does not document their memory needs either, so you don't have an idea
about how much free contiguous memory you need to compress a bunch of files
(repeatedly), this is the first thing so should try to find out, once you
have this value you should use it as a high watermark, you should check
before trying to compress whether you have such region of free memory in the
process, if you have you can start the compression task, if not you'll to
recover, for instance by a restart of the application (service or other) or
a restart the application domain.


Willy.
 
M

Marc Gravell

For illustration, the following (using #ziplib) handles multi-hundred-
megabite files with a very small memory footprint - worth giving it a
whirl? (you might be able to further optimise it with some bespoke
buffer code).

using System;
using ICSharpCode.SharpZipLib.Zip;

class Program {
static void Main(string[] args) {
using (ZipFile zip = ZipFile.Create(args[0])) {
zip.BeginUpdate();
for(int i = 1; i <args.Length; i++) {
zip.Add(args);
}
zip.CommitUpdate();
zip.Close();
}
}
}

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top