My colleagues and I have encountered an apparent bug in C#'s Graphics class. In our application, we update a bitmap over time by drawing new things on top of it. We use the Graphics.DrawImage(Image, Rectangle) method, and sometimes the call never returns, or even throw an exception. Is that an issue with which any of you are familiar?
Here's our use case:
Bitmap whole = ...;
This is defined well before our issue arises. The normal call looks like this, with 'part' and 'region' coming in from the network.:
Bitmap part = ...;
Rectangle region = ...;
using(var graphics = Graphics.FromImage(whole))
{
using(part)
{
graphics.DrawImage(part, region); // Execution stops in here
}
}
We tried putting a timeout on it:
...
var someAttributes = ... part ...;
var drawing = Task.Factory.StartNew(() => graphics.DrawImage(part, region));
if (!drawing.Wait(5000))
{
// We put a breakpoint here
}
...
We tried inspecting the 'part' image. Before the call, it looks ok; it's not disposed or anything and we're able to get its properties. But after the call, all its members throw InvalidOperationException.
If we let the program continue after this, the next calls will hang every single time. If we pause the debugger some time later, we can see in Threads view that these 'drawing' tasks are still waiting.
So if you know of any workaround, or a way to prevent this behaviour, your help will be greatly appreciated.
EDIT shortly after:
We looked into the graphics object and found that we could not inspect it because this "object is currently in use elsewhere". We thought that this was the only reference to the 'whole' image. We even cloned the image to display it in a picture box. We read up on Clone and found out, if we understood correctly, that it only does a shallow copy and still shares resources with the old image.
So we tried to replace
Rectangle subregion = ...;
Bitmap copy = whole.Clone(subregion);
with
Rectangle subregion = ...;
Bitmap copy = new Bitmap(whole.Clone(subregion));
and it seems to have solved our issue. Though it's still a problem that DrawImage doesn't throw an exception in that case.