on 03-29-2016 3:04 PM
Hi,
comparable to description of , I still do have the same problem.
The application runs as a windows service on Windows Server 2012.
I'm using Crystal Report v13.0.13 for .NET (x64 , Framework 4.5.2) with visual studio 2013.
Accourding to the "Fixed issues" at http://scn.sap.com/docs/DOC-7824 this problem has not been fixed in th newer releases.
The problem exits since we migrated the project from 32-bit to 64-bit and from VS 2008 to VS2013.
It is definitly Crystal R. that does not free the memory correctly.
Which further informations do you need to fix this bug?
Thanks in advance!
The thing to remember is that the Crystal and BO SDKs are based on COM objects, which can cause memory leaks if not handled correctly. So, when possible, you should either enclose calls to a report in the SDK with a "using" clause, or explicitly call .dispose() on the report when you're done with it.
-Dell
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thank you for your fast response. Unfortunately that's what I am already doing: .Dispose() on the Crystal R.-object and additionally on the DataSet and tables.
{ |
[...]
try | |
{ | |
[...] | |
crReportDocument = new ReportDocument(); | |
crReportDocument.Load(pathReport); | |
crReportDocument.SetDataSource(dsData); | |
crReportDocument.PrintOptions.PaperOrientation = CrystalDecisions.Shared.PaperOrientation.Landscape; | |
crReportDocument.SetParameterValue("finalized", false); |
if (myDestination.Equals(DestinationChoice.toDisk)) | |
{ | |
crReportDocument.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, fileWithPath); | |
} | |
else if (myDestination.Equals(DestinationChoice.toHttpResponse)) | |
{ | |
crReportDocument.ExportToHttpResponse(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, System.Web.HttpContext.Current.Response, true, filename); | |
} | |
} | |
catch (Exception ex) | |
{ | |
throw ex.ToString(); | |
} | |
finally | |
{ | |
if (crReportDocument != null) | |
{ | |
crReportDocument.Close(); | |
crReportDocument.Dispose(); | |
} | |
tabMaindata.Clear(); | |
tabMaindata.Dispose(); | |
tabSubrpdata.Clear(); | |
tabSubrpdata.Dispose(); | |
dsData.Clear(); //DataSet contains tabMaindata and tabSubrpdata | |
dsData.Dispose(); | |
} | |
} |
There are changes due to Crystal Report v13.0.17 for .NET.
The memory leak is still present, but smaller.
Summary of this thread:
* I am using the Release-build and the latest CR-version for .Net.
* I am releasing the CR-objects correctly (same results with using() and explicit dispose()).
* I am using all the suggested GC.Collect()-calls.
* The test-reports are prepared according to Dons suggestions.
Unfortunately that all has not improved anything.
SOLVED:
* The mentioned website-problems have been fixed in v13.0.17 (files in temp-folder) / solved by a workaround as described in this thread ("ThreadAbortException").
STILL AN ISSUE:
* Memory leak in windows service:
System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 138035200
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 101011456
<...creating 500 pdfs...>
System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 148779008
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 107872256
Memory consumption is growing meanwhile
about +10 MByte (initial: +12 MByte) for WorkingSet64, and
about +6 MByte (initial +13 MByte) for PrivateMemorySize64
per 500 created PDFs.
Do you need more infos/which further actions could I do?
Greetings
C. Lo
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
How do you know there is a memory leak? E.g.; errors? symptoms? behavior? What tool do you use the track the memory usage?
How do you know it is CR that is leaking?
- Ludek
Senior Support Engineer Product Support, Global Support Center Canada
Follow me on Twitter
Got Enhancement ideas? Use the SAP Idea Place
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Ludek,
the sourcecode is posted above, .Dispose() is in use.
For examination, we reduced the code and simulated all steps of the complete process during PDF-generation. Memory consumption was normal for each step, except when calling the crReportDocument.ExportToDisk() line. We logged the value returned by calling Process.GetCurrentProcess().WorkingSet64.ToString() for checking the memory.
After generating 25000 PDFs (within one run), the windows service requires over 420 MByte RAM, about 35 MByte would be normal. Calling garbage collection does not help:
GC.Collect(0, GCCollectionMode.Forced);
GC.Collect(1, GCCollectionMode.Forced);
GC.Collect(2, GCCollectionMode.Forced);
Thank you very much!
OK, but that doesn't show the dependencies being used, just the whole process.
Did you run in debug mode or Release mode? There are differences between the VS debug dll's and Release dll's.
Monitor the \temp folder and see if the files are being cleaned up. You may have to wait, Windows can take time, wait until the app is idle to see if they go away. And when closed do they get deleted?
Run Perfmon and watch the private byes on a release build of your app..
Are you using a report with saved data so it removed the DB client from the picture? Or even better just add a text object to the report with "Hello World" in it and run that report and select No Printer in the Page Setup, that removes the printer driver from the picture and relies on GDIPlus to format the page.
Also, when calling GC.Collect you need to add a few more lines:
GC.Collect();
|
Not all fixes will be listed in the readme file and any previous fixes automatically get rolled forward.
Don
Hi Don,
> Did you run in debug mode or Release mode? There are differences between the VS debug dll's and Release dll's.
Thank's for the hint, for project "A" we are using the debug-build only (a DLL for a windows service (issue: non-freeing memory) and for a website (issue: remaining temp-files).
Webproject "B" uses a 100% release-build with the same issue (remaining temp-files).
In the following I am checking your suggestions with both projects in release-mode.
Summary of tests: nothing changed, no break through. Maybe the exception-hint of the webproject at the end of this text is useful.
> Monitor the \temp folder and see if the files are being cleaned up.
> You may have to wait, Windows can take time, wait until the app is idle to see if they go away. And when closed do they get deleted?
Regarding webproject "B":
Partually. *.tmp-files remain (e.g. "tmp8DB6.tmp"). _That_ are the problem files.
> Run Perfmon and watch the private byes on a release build of your app..
webproject "B", before calling crReportDocument.ExportToHttpResponse(), 1. turn:
System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 234700800
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 208293888
2. turn:
System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 214327296
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 183783424
3.:
System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 200982528
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 169848832
4.:
System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 196390912
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 165408768
5.:
System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 194387968
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 163135488
6.:
System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 194822144
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 163696640
No growing memory consumption of the webpage.
project "A", Windows service:
System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 136384512
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 96813056
<...creating 500 pdfs...>
System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 148004864
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 110403584
Unreleased memory.
> Are you using a report with saved data so it removed the DB client from the picture?
> Or even better just add a text object to the report with "Hello World" in it and run that report and select No Printer in the Page Setup,
> that removes the printer driver from the picture and relies on GDIPlus to format the page.
That's what I did for testing:
1. logoff from any db connection
2. removing all picture objects (embedded and such ones set per formula)
3. Page Setup: No Printer
4. default config: don't save preview picture + already set: remove saved data (in english something like "skip saved data on loading")
5. Database: don't check with each printing
Does not help, nothing changed (both projects).
>Also, when calling GC.Collect you need to add a few more lines:
>> GC.Collect();
>> GC.WaitForPendingFinalizers();
>> GC.Collect();
Done. In addition I've added: Calling .Close() and .Dispose() on all SubReports.
Does not help (both projects).
> Not all fixes will be listed in the readme file and any previous fixes automatically get rolled forward.
Okay, thanks for that detail. I've updated to latest version 13.0.16 ("CRforVS_13_0_16.exe").
Still unreleased memory (in same dimension) / files like "tmp8DB6.tmp" remain in Windows temp-folder.
Does not help (both projects).
Greetings
C. Lo
Hints:
1. I have checked all above while running the project within Visual Studio 2013.
2. Regarding webproject "B":
In debug-mode I am getting this exception after calling .ExportToHttpResponse().
Nevertheless, after the exception (and after all the .Close()-calls, var. set to null etc.) the pdf is ready for download - and complete.
The exception contains this [translated], followed by the stack trace below:
"Der Ausdruck konnte..." = "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above."
"Der Thread wurde abgebrochen." = "Thread aborted."
- ex {"The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.} System.Exception {System.Threading.ThreadAbortException}
+ [System.Threading.ThreadAbortException] {"The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.} System.Threading.ThreadAbortException
_className null string
_data null System.Collections.IDictionary
_dynamicMethods null object
_exceptionMethod null System.Reflection.MethodBase
_exceptionMethodString null string
_helpURL null string
_HResult -2146233040 int
+ _innerException null System.Exception
+ _ipForWatsonBuckets 8791379550089 System.UIntPtr
_message "Thread has been aborted." string
_remoteStackIndex 0 int
_remoteStackTraceString null string
+ _safeSerializationManager {System.Runtime.Serialization.SafeSerializationManager} System.Runtime.Serialization.SafeSerializationManager
_source null string
+ _stackTrace {sbyte[384]} object {sbyte[]}
_stackTraceString null string
_watsonBuckets null object
_xcode -532462766 int
+ _xptrs 0 System.IntPtr
Data "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above. System.Collections.IDictionary
HelpLink "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above. string
HResult "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above. int
InnerException "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above. System.Exception
IPForWatsonBuckets "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above. System.UIntPtr
IsTransient "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above. bool
Message "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above. string
RemoteStackTrace "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above. string
Source "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above. string
StackTrace "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above. string
TargetSite "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above. System.Reflection.MethodBase
WatsonBuckets "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above. object
Stack trace (first lines are the latest):
mscorlib.dll!System.Threading.Thread.Abort(object stateInfo = {unknown}) C#
System.Web.dll!System.Web.HttpResponse.AbortCurrentThread() C#
CrystalDecisions.Shared.dll!CrystalDecisions.Shared.SharedUtils.WriteToResponse(System.Web.HttpResponse response = {unknown}, System.IO.Stream inputStream = {unknown}, bool exclusive = {unknown}) C#
CrystalDecisions.CrystalReports.Engine.dll!CrystalDecisions.CrystalReports.Engine.ReportDocument.ExportToHttpResponse(CrystalDecisions.Shared.ExportOptions options = {unknown}, System.Web.HttpResponse response = {unknown}, bool asAttachment = {unknown}, string attachmentName = {unknown}) C#
CrystalDecisions.CrystalReports.Engine.dll!CrystalDecisions.CrystalReports.Engine.ReportDocument.ExportToHttpResponse(CrystalDecisions.Shared.ExportFormatType formatType = {unknown}, System.Web.HttpResponse response = {unknown}, bool asAttachment = {unknown}, string attachmentName = {unknown}) C#
my_Website.dll!my_Website.presentation.my_Page.btn_Print_Click(object sender = {unknown}, System.EventArgs e = {unknown}) C#
(end of text)
I've implemented the suggestion of Dell Stinett-Christy, calling the export with a "using" clause
(without and with trying to clean the ReportDocument via .Close&.Dispose in an additional catch()-routine).
Still unreleased memory (in same dimension) / files like "tmp8DB6.tmp" remain in Windows temp-folder.
System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 135520256
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 96231424
<...creating 500 pdfs...>
System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 146440192
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 102490112
Does not help (both projects).
Is the following of interest?
project "A" (windows service) uses these Crystal-references:
webproject "B" uses these Crystal-references:
If you stop the service does it clean up those temp files?
When our engine finishes with a report it should close and delete all temp files we ask the OS to create. Or at least mark them as can be deleted. Sometimes the Hardware is slow to respond to the request.
How about permissions? CR requires full read/write to the System temp folder so it can export. When exporting it first tries to write the file and then delete it to see if the process has full rights. If not it can leave behind files.
Possibly Firewall and/or AV software is blocking access....
Don
Hi Don,
you are right, but: yes and yes. That's why & how our workaround works:
project "A" (windows service) - the service restarts programmaticaly, when it is consuming more than x-hundred MBytes of RAM. After that, complete memory is released.
webproject "B" - the webpage is deleting all *.tmp-files (older than xy) from the windows temp-folder, when doing something regarding pdf-creation. (Before that, we were running into the ">32k files in win-temp-folder-problem".)
> Possibly Firewall and/or AV software is blocking access
Nope, same behaviour on DEV-machine as on productive environment.
Greetings
C. Lo
Hi C,
That would be normal, as the project loads CR runtime it will typically grow to 100 meg, and this is known and confirmed by DEV. So when running stress tests etc. it is typical for the app to consume that much memory.
I had some of those TMP*.tmp files also but they were not owned by CR. I closed all CR app's and designers, deleted all file int he temp folder which were not locked and ran my WEB app in both IISExpress ( debug mode ) and using IIS on my Windows 10 image and I did not see any of those TMP files being generated.
I did see a lot of ~cre*.tmp file created and a few that started with D.... but they were deleted after I changed IIS from 32 to 64 bit mode. Both modes created the same number of files and none were TMP*.tmp files.
I did some more testing and closed VS and ran the test app from IIS and I don't see any temp files being created in the User \temp folder.
I'll do more testing and see if I can figure this out....
Don
Hi Don,
> If you stop the service does it clean up those temp files?
The service has no remaining temp files. The webproject does not clean up the mentioned temp-files.
Regarding webproject "B":
yes, we are using sessions for the website (no cookies).
Looking at the history of this thread - shall I prepare a VS-project with our *.RPT for debugging that on your own?
It is no CR-migration-problem (update from CR-vXY), because it the same with a newly created RPT (with VS 2013).
UPDATE June-2: There is no difference between using IIS Server / ISS Express (except of the temp-folder located in the user-dir. \AppData\Local\Temp).
UPDATE June-11: At least this is fixed now: "C. Lo May 11, 2016 2:59 PM", exception without useful content while calling CR-method. It is a System.Threading.ThreadAbortException error.
-> Instead of calling crystals ExportToHttpResponse()-method, this works as mentioned in , from the year 2011 (my implementation differs a bit):
Stream crstream = crReportDocument.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);//, System.Web.HttpContext.Current.Response, true, fileName);
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment; filename=\"" + fileName + ".pdf\"");
byte[] buffer = new byte[4096];
int count = 0;
while ((count = crstream.Read(buffer, 0, buffer.Length)) > 0) //this provides a correct value in HTML headerfield "Content-Length"
{
Response.OutputStream.Write(buffer, 0, count);
Response.Flush();
}
HttpContext.Current.ApplicationInstance.CompleteRequest();
//Response.End(); <--this line produces a similar error like ExportToHttpResponse() -> "ThreadAbortException: Thread has been aborted."
Meanwhile any further hints or ideas?
Greetings
C. Lo
Message was edited by: C. Lo: solution added for System.Threading.ThreadAbortException
User | Count |
---|---|
93 | |
11 | |
10 | |
9 | |
9 | |
7 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.