windows C++-移除界面工作线程(一)

news2024/11/26 16:14:18

本文档演示了如何使用并发运行时将 Microsoft 基础类 (MFC) 应用程序中由用户界面 (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_ptr<Gdiplus::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_cast<int*>(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_cast<BYTE>((iter % 64) * 4);
            *destPixel = red<<16;
         }

         // 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 应用程序的结果。 

a35a42fc7fc640e89adca095f1b1bd7a.png

由于每个像素的计算成本很高,因此在总体计算完成之前,UI 线程无法处理其他消息。 这可能会降低应用程序的响应能力。 但是,可以通过从 UI 线程中移除工作来缓解此问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2201535.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python爬虫使用示例-古诗词摘录

一、分析需求 目标地址&#xff1a; https://www.sou-yun.cn/Query.aspx?typepoem&id二、提取诗句 import os import re import requests import parsel#url https://www.sou-yun.cn/PoemIndex.aspx?dynastyTang&author14976&typeJie urlhttps://www.sou-yun.…

移动app的UI和接口自动化测试怎么进行?

标题&#xff1a;从0到1&#xff1a;移动App的UI和接口自动化测试 导语&#xff1a;移动App的快速发展使得UI和接口自动化测试成为了确保应用质量的重要环节。本文将从零开始介绍移动App的UI和接口自动化测试的基本概念以及如何进行测试。 第一部分&#xff1a;了解移动App自动…

【React】如何在MacBook的vscode中配置React环境

作者&#xff1a;CSDN-PleaSure乐事 欢迎大家阅读我的博客 希望大家喜欢 使用环境&#xff1a;Vscode 安装Node.js和npm 首先我们需要完成Node和npm的配置。 官网下载 下载安装包 首先最安全稳定的方法就是从官网下载。我们首先进入node.js的官网https://nodejs.org下载长期…

如何让你的Mac右键菜单栏更加的丰富多样

Mac电脑的右键菜单栏不如Windows的丰富&#xff0c;虽然可以在系统设置一些常用功能&#xff0c;但是种类不够丰富&#xff0c;这对于一些用惯了Windows的人来说可以说是非常的不习惯&#xff0c;不管是工作使用还是日常使用来说都有一些影响&#xff0c;如何才能让Mac的右键菜…

日常场景图像分割系统源码&数据集分享

日常场景图像分割系统源码&#xff06;数据集分享 [yolov8-seg-LSKNet&#xff06;yolov8-seg-LAWDS等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目来源AAAI Global Al lnnov…

如何解决与kernel32.dll相关的常见错误:详细指南解析kernel32.dll文件缺失、损坏或错误加载问题

当你的电脑中出现错误kernel32.dll丢失的问题&#xff0c;会导致电脑不能出现正常运行&#xff0c;希望能够有效的帮助你有效的将丢失的kernel32.dll文件进行修复同时也给大家介绍一些关于kernel32.dll文件的相关介绍&#xff0c;希望能够有效的帮助你快速修复错误。 kernel32.…

Golang | Leetcode Golang题解之第464题我能赢吗

题目&#xff1a; 题解&#xff1a; func canIWin(maxChoosableInteger, desiredTotal int) bool {if (1maxChoosableInteger)*maxChoosableInteger/2 < desiredTotal {return false}dp : make([]int8, 1<<maxChoosableInteger)for i : range dp {dp[i] -1}var dfs …

实战OpenCV之视频处理

基础入门 视频是由一系列连续的图像帧组成的&#xff0c;这些帧按照一定的速率连续播放&#xff0c;从而形成动态画面。与视频相关的主要参数有&#xff1a;分辨率、帧率、码率、编解码器、帧类型、文件格式等&#xff0c;下面分别进行介绍。 1、帧率。表示每秒显示的图像帧数&…

(01)python-opencv基础知识入门(图片的读取与视频打开)

前言 一、图像入门 1.1 读取图像cv.imread() 1.2 数组数据转换cv.cvtColor() 1.3数据窗口展示 1.4图像保存 1.5图像的截取 1.6 图像的比例缩放 二、视频入门 参考文献 前言 OpenCV 于 1999 年由 Gary Bradsky 在英特尔创立&#xff0c;第一个版本于 2000 年问世。Vad…

Golang | Leetcode Golang题解之第468题验证IP地址

题目&#xff1a; 题解&#xff1a; func validIPAddress(queryIP string) string {if sp : strings.Split(queryIP, "."); len(sp) 4 {for _, s : range sp {if len(s) > 1 && s[0] 0 {return "Neither"}if v, err : strconv.Atoi(s); err …

毕业设计项目-古典舞在线交流平台的设计与实现(源码/论文)

项目简介 基于springboot实现的&#xff0c;主要功能如下&#xff1a; 技术栈 后端框框&#xff1a;springboot/mybatis 前端框架&#xff1a;html/JavaScript/Css/vue/elementui 运行环境&#xff1a;JDK1.8/MySQL5.7/idea&#xff08;可选&#xff09;/Maven3&#xff08…

一台电脑轻松接入CANFD总线-来可CAN板卡介绍

在工业控制领域&#xff0c;常常使用的总线技术有CAN(FD)、RS-232、RS-485、Modbus、Profibus、Profinet、EtherCAT等。RS-485以其长距离通信能力著称&#xff0c;Modbus广泛应用于PLC等设备&#xff0c;EtherCAT则以其低延迟和高实时性在自动化系统中备受青睐。 其中&#xf…

实时开放词汇目标检测(论文复现)

实时开放词汇目标检测&#xff08;论文复现&#xff09; 本文所涉及所有资源均在传知代码平台可获取 文章目录 实时开放词汇目标检测&#xff08;论文复现&#xff09;概述模型框架使用方式配置环境训练和评估训练评估 演示效果Gradio Demo 概述 YOLO-World是由腾讯人工智能实验…

Comfyui 学习笔记5

1.图像处理小工具&#xff0c;沿某个轴反转Image Flip 2. reactor换脸 3. 通过某人的多张照片进行训练 训练的模型会保存在 models/reactor/face/下面&#xff0c;使用时直接load就好 4. 为一个mask 更加模糊 羽化 5. 指定位置替换&#xff0c;个人感觉这种方式进行换脸的融…

评职称需要讲究方法

评职称需要讲究方法 评职称不要太老实 你评三年没下来 你同事走“野路子” 一年就下来了 所以别吃亏了 不走的弯路别走 不该吃的苦别吃 大家如果对于职称评审业绩材料整理还有什么不懂的&#xff0c;可以在评论区留言&#xff0c;甘建二告诉你们怎么报职称&#xff0c;少…

4.C语言概念之旅:解锁关键字,字符,字符串的秘密,揭秘语句和注释,程序员的宝藏

C语言概念之旅&#xff1a;解锁关键字&#xff0c;字符&#xff0c;字符串的秘密&#xff0c;揭秘语句和注释&#xff0c;程序员的宝藏 C语言往期系列文章目录 往期回顾&#xff1a; C语言是什么&#xff1f;编程界的‘常青树’&#xff0c;它的辉煌你不可不知VS 2022 社区版…

Java | Leetcode Java题解之第468题验证IP地址

题目&#xff1a; 题解&#xff1a; class Solution {public String validIPAddress(String queryIP) {if (queryIP.indexOf(.) > 0) {// IPv4int last -1;for (int i 0; i < 4; i) {int cur (i 3 ? queryIP.length() : queryIP.indexOf(., last 1));if (cur <…

优雅的实现服务调用 -- OpenFeign

文章目录 1. RestTemplate存在问题2. OpenFeign介绍3. 快速上手引入依赖添加注解编写OpenFeign的客户端远程调用 4. OpenFeign参数传递从URL中获取参数传递单个参数传递多个参数传递对象传递JSON 5. 最佳实践Feign继承方式创建一个新的模块引入依赖编写接口打jar包服务实现方实…

锐龙7 7800X3D与i7-14700K到底怎么选!其实很简单

从2022年的锐龙7 5800X3D到后来的锐龙7 7800X3D&#xff0c;笔者使用X3D处理器已有2年多的时间。站在自己的立场&#xff0c;我是非常希望游戏老鸟购买这类处理器的&#xff0c;并且也推荐了不少。 这里说的是老鸟&#xff0c;也就是比较懂电脑的玩家。 但是对于新手玩家而言&a…

Canal 扩展篇(阿里开源用于数据同步备份,监控表和表字段(日志))

1.Canal介绍 Canal把自己伪装成从数据库&#xff0c;获取mysql主数据库的日志&#xff08;binlog&#xff09;信息&#xff0c;所以要想使用canal就得先开启数据库日志 https://github.com/alibaba/canal Canal 主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量…