I'm improving the performance of a 3d engine i created, introducing LockBits and parallel processing. I have a class for the engine with the following method to update a bitmap with the result:
public void draw() {
clearbmp();
// locking bmp
BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, W, H), ImageLockMode.ReadWrite, bmp.PixelFormat);
IntPtr FirstPixel = bitmapData.Scan0;
int bytes = Math.Abs(bitmapData.Stride) * H;
bpp = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8;
rgbarray = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(FirstPixel, rgbarray, 0, bytes);
int count = 0;
for (int k = 0; k < solidos.Count; k++)
{
if (solidos[k] != null && solidos[k].draw)
{
// separating faces of the solid into different threads
Parallel.ForEach(solidos[k].side, f =>
{
// ... do the operations...
});
}
}
// copy the array to the bitmap and unlock
System.Runtime.InteropServices.Marshal.Copy(rgbarray, 0, FirstPixel, bytes);
bmp.UnlockBits(bitmapData);
The code runs as intended to generate a image, but fails when the main program requires it to update several times in a quick succession, the error occurs in bmp.UnlockBits(bitmapData) with the excepion "Generic error in GDI+"
From what i gathered from my research I suppose this happens because the method runs a second time before it finished the first one, thus trying to unlock data that is already unlocked.
If that is correct then how can i abort the running thread when the new one is created? The last call is always the important one
lock
region. This solves the correctness issue. Maybe it's easier to make each computation run into aTask
usingTask.Run
. The resultingTask
object is a handle to that computation and can be used to wait for it to complete.volatile bool cancel = false;
. Set it totrue
to cancel. In your parallel loop (and possibly elsewhere), check that boolean variable periodically and terminate if it is foundtrue
. You can also use aCancellationTokenSource
.