成都捕鱼网站建设,wordpress原有注册登录页面,做网站哪家最好,中国建筑第八工程局有限公司本文档演示了如何使用并发运行时将 Microsoft 基础类 (MFC) 应用程序中由用户界面 (UI) 线程执行的工作移动到工作线程。 本文档还演示了如何提高冗长绘制操作的性能。
通过将阻塞性操作#xff08;例如#xff0c;绘制#xff09;卸载到工作线程来从 UI 线程中移除工作例如绘制卸载到工作线程来从 UI 线程中移除工作可以提高应用程序的响应能力。本文使用可生成 Mandelbrot 分形的绘制例程来演示一个冗长的阻塞性操作。 Mandelbrot 分形的生成也非常适合并行化因为每个像素的计算都是独立于所有其他计算的。
创建 Visual C MFC 应用程序
使用“MFC 应用程序向导”创建具有所有默认设置的 MFC 应用程序。 有关如何为 Visual Studio 版本打开向导的说明请参阅演练使用新的 MFC Shell 控件。
为项目键入一个名称例如 Mandelbrot然后单击“确定”以显示“MFC 应用程序向导”。
在“应用程序类型”窗格中选择“单个文档”。 确保清除“文档/视图体系结构支持”复选框。
单击“完成”以创建项目并关闭“MFC 应用程序向导”。
通过生成并运行应用程序来验证其是否已成功创建。 若要生成应用程序请在“生成”菜单上单击“生成解决方案”。 如果应用程序已成功生成请单击“调试”菜单上的“开始调试”来运行应用程序。
实现 Mandelbrot 应用程序的串行版本
本部分介绍了如何绘制 Mandelbrot 分形。 此版本将 Mandelbrot 分形绘制到 GDI 位图对象然后将该位图的内容复制到客户端窗口。下面的代码实现 Mandelbrot 应用程序的串行版本
// 1.在 pch.h在 Visual Studio 2017 及更早版本中为 stdafx.h中添加以下 #include 指令#include memory// 2. 在 ChildView.h 中在 pragma 指令后面定义 BitmapPtr 类型。
// BitmapPtr 类型允许使用一个指向要由多个组件共享的 Bitmap 对象的指针。
// 当任何组件都不再引用 Bitmap 对象时该对象将被删除。typedef std::shared_ptrGdiplus::Bitmap BitmapPtr;// 3. 在 ChildView.h 中将以下代码添加到 CChildView 类的 protected 部分protected:// Draws the Mandelbrot fractal to the specified Bitmap object.void DrawMandelbrot(BitmapPtr);protected:ULONG_PTR m_gdiplusToken;// 4. 在 ChildView.cpp 中注释掉或移除以下行。
//#ifdef _DEBUG
//#define new DEBUG_NEW
//#endif// 5. 在调试内部版本中此步骤将阻止应用程序使用与 GDI 不兼容的 DEBUG_NEW 分配器。
// 在 ChildView.cpp 中向 Gdiplus 命名空间添加一个 using 指令。
using namespace Gdiplus;// 6. 将以下代码添加到 CChildView 类的构造函数和析构函数以初始化和关闭 GDI。CChildView::CChildView()
{// Initialize GDI.GdiplusStartupInput gdiplusStartupInput;GdiplusStartup(m_gdiplusToken, gdiplusStartupInput, NULL);
}CChildView::~CChildView()
{// Shutdown GDI.GdiplusShutdown(m_gdiplusToken);
}// 7. 实现 CChildView::DrawMandelbrot 方法。
// 此方法会将 Mandelbrot 分形绘制到指定的 Bitmap 对象。
// Draws the Mandelbrot fractal to the specified Bitmap object.
void CChildView::DrawMandelbrot(BitmapPtr pBitmap)
{if (pBitmap NULL)return;// Get the size of the bitmap.const UINT width pBitmap-GetWidth();const UINT height pBitmap-GetHeight();// Return if either width or height is zero.if (width 0 || height 0)return;// Lock the bitmap into system memory.BitmapData bitmapData; Rect rectBmp(0, 0, width, height);pBitmap-LockBits(rectBmp, ImageLockModeWrite, PixelFormat32bppRGB, bitmapData);// Obtain a pointer to the bitmap bits.int* bits reinterpret_castint*(bitmapData.Scan0);// Real and imaginary bounds of the complex plane.double re_min -2.1;double re_max 1.0;double im_min -1.3;double im_max 1.3;// Factors for mapping from image coordinates to coordinates on the complex plane.double re_factor (re_max - re_min) / (width - 1);double im_factor (im_max - im_min) / (height - 1);// The maximum number of iterations to perform on each point.const UINT max_iterations 1000;// Compute whether each point lies in the Mandelbrot set.for (UINT row 0u; row height; row){// Obtain a pointer to the bitmap bits for the current row.int *destPixel bits (row * width);// Convert from image coordinate to coordinate on the complex plane.double y0 im_max - (row * im_factor);for (UINT col 0u; col width; col){// Convert from image coordinate to coordinate on the complex plane.double x0 re_min col * re_factor;double x x0;double y y0;UINT iter 0;double x_sq, y_sq;while (iter max_iterations ((x_sq x*x) (y_sq y*y) 4)){double temp x_sq - y_sq x0;y 2 * x * y y0;x temp;iter;}// If the point is in the set (or approximately close to it), color// the pixel black.if(iter max_iterations) { *destPixel 0;}// Otherwise, select a color that is based on the current iteration.else{BYTE red static_castBYTE((iter % 64) * 4);*destPixel red16;}// Move to the next point.destPixel;}}// Unlock the bitmap from system memory.pBitmap-UnlockBits(bitmapData);
}// 7. 实现 CChildView::OnPaint 方法。 此方法将调用 CChildView::DrawMandelbrot
// 然后将 Bitmap 对象的内容复制到窗口。
void CChildView::OnPaint()
{CPaintDC dc(this); // device context for painting// Get the size of the client area of the window.RECT rc;GetClientRect(rc);// Create a Bitmap object that has the width and height of // the client area.BitmapPtr pBitmap(new Bitmap(rc.right, rc.bottom));if (pBitmap ! NULL){// Draw the Mandelbrot fractal to the bitmap.DrawMandelbrot(pBitmap);// Draw the bitmap to the client area.Graphics g(dc);g.DrawImage(pBitmap.get(), 0, 0);}
}
// 8. 通过生成并运行应用程序来验证其是否已成功更新。
下图显示了 Mandelbrot 应用程序的结果。 由于每个像素的计算成本很高因此在总体计算完成之前UI 线程无法处理其他消息。 这可能会降低应用程序的响应能力。 但是可以通过从 UI 线程中移除工作来缓解此问题。