// Copies a MandImage object AND its bitmap from the source to this object. public void CopyFrom(MandImage sourceMandelbrotImage) { if (ReferenceEquals(this, sourceMandelbrotImage)) { // Don't bother copying because we're trying to copy the same object. return; } MandRect.CopyFrom(sourceMandelbrotImage.MandRect); // Copy bitmap. if (MainBmp.Size != sourceMandelbrotImage.MainBmp.Size) { throw (new Exception("Bitmap sizes do not match hence can't be copied in MandImage.CopyFrom()")); } else { using (Graphics g = Graphics.FromImage(MainBmp)) { g.DrawImage(sourceMandelbrotImage.MainBmp, 0, 0); } } m_bitmapCalculated = sourceMandelbrotImage.m_bitmapCalculated; formToUpdate = sourceMandelbrotImage.formToUpdate; XInc = sourceMandelbrotImage.XInc; YInc = sourceMandelbrotImage.YInc; bitmapSectionCalcFinishedDelegate = sourceMandelbrotImage.bitmapSectionCalcFinishedDelegate; bitmapCalcFinishedDelegate = sourceMandelbrotImage.bitmapCalcFinishedDelegate; }
/// <summary> /// Activates a series of threads up to maxThreads, each of which will calculate the points in successive sections of the image, defined by a start and stop row in threadInfo and /// Form1.mandRect.X, mandRect.Right, mandRect.Y, mandRect.Bottom, xInc and yInc which define the mandelbrot value range that maps to the overall bitmap to be generated. /// /// Checks that noRowsCalcd is 0 and if it’s not, issue error msg that we tried to recalc whilst a recalc was already underway and return. /// If it is zero, for 0 to maxThreads – 1, call AddImageCalcThread for the relevant threadInfo element. /// /// </summary> public void CalcMandelbrotImage(BitmapSectionCalcFinishedDelegate myBitmapSectionCalcFinishedDelegate, BitmapCalcFinishedDelegate myBitmapCalcFinishedDelegate) { // Update the delegate that should be called to notify when each bitmap section is finished so the form can render this section. bitmapSectionCalcFinishedDelegate = myBitmapSectionCalcFinishedDelegate; // Update the delegate that should be called to notify when the entire bitmap is finished calculating. bitmapCalcFinishedDelegate = myBitmapCalcFinishedDelegate; // Queue the task. // threadsActive = true; // ThreadInfo ti = new ThreadInfo(); // ti.bmp = (Bitmap)MainBmp.Clone(); // tiArrayList.Add(ti); // ThreadPool.QueueUserWorkItem(new WaitCallback(createMandlebrotImage), ti); if (numberActiveBackGroundThreads != 0) { MessageBox.Show("Error - cannot complete calculations as " + numberActiveBackGroundThreads + " caculcation threads already underway.", "Calculation Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } // Grab lock to make sure that no other thread updates the imageCalcInProgress etc. lock (_locker) { imageCalcInProgress = true; // Divide number of rows of bitmap to calc into chunks of rowsToCalcPerThread for (int threadNum = 0; threadNum < maxThreads; threadNum++) { if (threadInfoArray[threadNum].bwThread.IsBusy) { // This thread is not available throw new Exception("ERROR - numberActiveBackGroundThreads = 0 but thread " + threadNum + " is active."); } else { // Thread is available so set it up and start it. ThreadInfo ti = threadInfoArray[threadNum]; ti.fullMandImage = this; SetAndActivateThreadToCalcNextImageSection(ti); } } } }