Welcome Guest! To enable all features, please Login or Register.

Notification

Icon
Error

Options
View
Last Go to last post Unread Go to first unread post
#1 Posted : Wednesday, November 5, 2008 4:23:33 AM(UTC)
dr_bogenbroom

Groups: Registered
Posts: 10


Hello,
We seem to be having an intermittent issue with CreateLeadDC.  We are using C# and VS2005, LT v15
latest patches (Leadtools.Codecs.dll version: 15.0.1.17).

Here is the issue:
Originally we had many problems with creategdiplus calls to draw on an image before saving it.  We fought, and
fought and then after reading some forum posts changed to using CreateLeadDC and using Graphics.FromHdc
to get a graphics object we could draw on.  This all seemed to be working fine until during testing the other day
we discovered that once in a while the pointer returned by CreateLeadDC caused a NULL pointer exception
when calling Graphics.FromHdc on it.  What is odd is if I try calling our save command again, it may work.  Sometimes
I have to try it a few times, but usually it will eventually work.  Any ideas on what would cause this.  Is there any additional
error information I could get (possibly through calling Marshal.GetLastWin32Error).  What would cause CreateLeadDC
to return IntPtr.Zero every once in a while.  It is very hard to debug this problem since I can't reliably reproduce it.  It
happens intermittently.  Could this be memory related?  Any ideas would be helpful.

Code snippet:
IntPtr hdc = image.CreateLeadDC();
Graphics graphics = Graphics.FromHdc(hdc); // This is the call that throws the exception

Thanks!

 

Try the latest version of LEADTOOLS for free for 60 days by downloading the evaluation: https://www.leadtools.com/downloads

Wanna join the discussion? Login to your LEADTOOLS Support accountor Register a new forum account.

#2 Posted : Wednesday, November 5, 2008 4:31:33 AM(UTC)
dr_bogenbroom

Groups: Registered
Posts: 10


I should also note that it seems like I can only reproduce this on Vista (32 bit is what we were testing on at the time)
 
#3 Posted : Wednesday, November 5, 2008 5:49:31 AM(UTC)
Maen Hasan

Groups: Registered, Tech Support
Posts: 1,328

Was thanked: 1 time(s) in 1 post(s)

I checked the same issue on windows vista and didn't notice the problem. Did you check the same issue on a different machine?

I am attaching the C# VS2005 project that I used to check this issue.
Please recheck the same issue using the attached project and let me know how it goes.

Thanks,
Maen Badwan
LEADTOOLS Technical Support
File Attachment(s):
CsTestCreateLeadDC2005.zip (10kb) downloaded 20 time(s).
 
#4 Posted : Wednesday, November 5, 2008 9:13:03 AM(UTC)
dr_bogenbroom

Groups: Registered
Posts: 10


I have a sample app that will reproduce this issue fairly reliably on Vista (I was able to reproduce the issue on XP64 a couple of times as well, but it was much more difficult to reproduce the error there, on Vista it fails almost every time).


File Attachment(s):
SampleApp.zip (40kb) downloaded 19 time(s).
 
#5 Posted : Wednesday, November 5, 2008 10:24:40 AM(UTC)
dr_bogenbroom

Groups: Registered
Posts: 10


Here is a copy of the main function for the attached sample application I produced that will fix the issue.  This is not an elegant solution by any stretch of the imagination, but I have found it to work every time and only require one loop iteration when the call to CreateLeadDC fails.  The fix is to check the return value of CreateLeadDC and if it is IntPtr.Zero, dispose of the page, call garbage collection and wait for the finalizers, then reclone the page, reconvert it, and then call CreateLeadDC again.  It seems (at least on my test system which is a 2 GHZ quad core with 2 GB of RAM) to only add about .1 second to the total time and to only need to be done once (the loop count that is printed out has been 1 each time).  This seems like a bad fix, but it will work for my purposes, I wish there was a better way as from my understanding it is not good to force a garbage collection.

        static void Main(string[] args)
        {
            int count = 0;
            try
            {
                RasterSupport.Unlock(RasterSupportType.Document, "");

                RasterCodecs.Startup();

                RasterCodecs codecs = new RasterCodecs();

                string fileName = @"C:\test\test.tif";

                codecs.Options.Tiff.Load.IgnoreViewPerspective = true;

                RasterImage newImage = codecs.Load(fileName);

                for (; count < 500; count++)
                {
                    ColorResolutionCommand command = new ColorResolutionCommand();
                    command.BitsPerPixel = 16;
                    command.DitheringMethod = RasterDitheringMethod.FloydStein;
                    command.Mode = ColorResolutionCommandMode.InPlace;
                    RasterImage imageToSave = null;
                    for (int i = 1; i <= newImage.PageCount; i++)
                    {
                        newImage.Page = i;
                        RasterImage page = newImage.Clone();

                        if (newImage.BitsPerPixel < 16)
                        {
                            command.Run(page);
                        }

                        IntPtr hdc = page.CreateLeadDC();

                        DateTime time = DateTime.Now;
                        int loopCount = 0;
                        while (hdc == IntPtr.Zero)
                        {
                            page.Dispose();

                            GC.Collect();
                            GC.WaitForPendingFinalizers();

                            page = newImage.Clone();

                            if (newImage.BitsPerPixel < 16)
                            {
                                command.Run(page);
                            }

                            hdc = page.CreateLeadDC();
                            loopCount++;
                        }

                        if (loopCount > 0)
                        {
                            string timeSpan = " Time: " + ((TimeSpan)(DateTime.Now - time)).Milliseconds.ToString();
                            Console.WriteLine("Count: " + count.ToString() + " Loop count: " + loopCount.ToString() + timeSpan);
                        }

                        Graphics graphics = Graphics.FromHdc(hdc);

                        RasterImage.DeleteLeadDC(hdc);
                        graphics.Dispose();

                        if (imageToSave == null)
                        {
                            imageToSave = page;
                        }
                        else
                        {
                            imageToSave.AddPage(page);
                        }
                    }

                    codecs.Save(imageToSave, fileName + "." + count.ToString() + ".save.tif", RasterImageFormat.CcittGroup4,
                        0, 1, -1, 1, CodecsSavePageMode.Overwrite);
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception");
                Console.WriteLine("Count: " + count.ToString());
                Console.WriteLine(ex.Message);
            }
            finally
            {
                RasterCodecs.Shutdown();
            }
        }

 
#6 Posted : Thursday, November 6, 2008 7:12:25 AM(UTC)
Maen Hasan

Groups: Registered, Tech Support
Posts: 1,328

Was thanked: 1 time(s) in 1 post(s)

I did a quick test using your project and saw that CreateLeadDC does fail sometimes. However I do not expect this to be an actual problem in our toolkit, since the Device Context handle (DC) our function creates is actually a Windows resource. If we request this resource from Windows and we don't get it, it might be caused by exceeding some limitation in Windows itself.

This means the workaround you found might be more elegant than you thought, because it forces .NET to free some resources and make them available to the application. However, if you believe it is not acceptable, please send a message to support@leadtools.com and mention this post, and I will investigate it more and possibly report it to our engineers.

Thanks,
Maen Badwan
LEADTOOLS Technical Support
 
#7 Posted : Thursday, November 6, 2008 7:40:12 AM(UTC)
dr_bogenbroom

Groups: Registered
Posts: 10


Maen,
It seems to me from the simple app's perspective, not much has been allocated as far as resources go, and its hard to explain what is causing it to fail.  The problem is only rarely reproduceable on other OS's, but on Vista it almost always fails.  I only had it successfully pass a few times.  From my perspective I think there is still an issue, and if not with the toolkit, what is very distressing is that there was no useful error information (I tried getting the last win32 error after the call failed and all I got was "Call completed successfully").  If nothing else, some error information that may have led to a workaround would have been nice.  Maybe the desire to avoid throwing an exception was a good idea, but then some other mechanism to get the error info when the call failed to return a valid device context would have been helpful and almost certainly would have helped me to track this down faster and come up with a workaround sooner.  Maybe the workaround I found would be better suited inside the function, I am not sure, but in general if a call fails it is very helpful from a developers perspective to find out why it failed.  The garbage collection work around was an educated guess based on the the behavior that if when the call failed I disposed of the page I was working on and tried again (repeatedly, sometimes up to 500 times) that it would work, which led to the thought that the issue may be somehow resource related, and honestly leads me to believe that the issue is not necessarily with the CreateLeadDC call, but actually with the Clone call, since I couldn't seem to create a DC on the same image page once it failed.  The workaround was to dispose of the page and then it could eventually create one.  Anyway, I am rambling here, I just think it might be helpful to pass this along to the developers to look at as there may be some improvement (if only in the area of getting error information) that could be made.
 
#8 Posted : Friday, November 7, 2008 9:11:48 AM(UTC)

jigar  
Guest

Groups: Guests
Posts: 3,034

Was thanked: 2 time(s) in 2 post(s)

Hello,

I tested out the demo app you sent me and I let it run for 600 iterations, and it didn't give me any errors.  I did notice the memory increasing in the task manager.  It would go up to the available memory on the system and then it would drop back down.  The process' memory itself doesn't go up, but if you look at the Performance tab, you will see the totally system memory usage climb ~22mb on each iteration.  Seems to be doing garbage collection when it's close to running out of memory.  To fix that you need to call image.Dispose() after you save it out.  Then you can set it to null.
 
#9 Posted : Sunday, November 9, 2008 4:24:29 AM(UTC)
Maen Hasan

Groups: Registered, Tech Support
Posts: 1,328

Was thanked: 1 time(s) in 1 post(s)

I rechecked the same issue several times on windows vista and didn't get the same problem. It seems the problem rarely happens.
As I told you, if we request Device Context handle (DC) resource from Windows and we don't get it, it might be caused by exceeding some limitation in Windows itself.

If you check the same issue outside the debugger (using the Exe), do you notice the same problem?

Thanks,
Maen Badwan
LEADTOOLS Technical Support
 
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Powered by YAF.NET | YAF.NET © 2003-2020, Yet Another Forum.NET
This page was generated in 0.361 seconds.