每次处理并行任务时,如果要等待用户输入或依赖外部(如与灿亨控制器响应),就应该为类似的操作单独创建一个线程,这样我们的程序才不会挂起无响应。
静态库和动态库
静态库是指在程序运行前就编译完成的库,如#include行为;
动态库指在程序运行时进行链接的库,如user32.dll.

一、事件处理器和消息传递接口

该程序演示了一个只有关闭功能的窗口


#include <Windows.h> //处理一些视觉特效,例如窗口,控件,枚举,样式

//在创建一个应用程序之前,必须先声明一个窗口过程的原型才能在窗口结构中使用它
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

//WINAPI或stdcall意味着栈的清理工作由被调用函数来完成
//hThis是应用程序当前实例的句柄;hPrev是应用程序上一个实例的句柄;
//szCmdLine是应用程序的命令行,包括该程序的名称;iCmdShow控制如何显示窗口
int WINAPI WinMain(HINSTANCE hThis, HINSTANCE hPrev, LPSTR szCmdLine, int iCmdShow)
{
    UNREFERENCED_PARAMETER(hPrev); //告诉编译器不能使用某些参数,方便编译器进行一些额外的优化
    UNREFERENCED_PARAMETER(szCmdLine);

    WNDCLASSEX wndEx = { 0 }; //实例化窗口结构
    wndEx.cbClsExtra = 0; //实例化窗口类后分配的额外字节数
    wndEx.cbSize = sizeof(wndEx); //窗口结构的大小(字节为单位)
    wndEx.cbWndExtra = 0; //实例化窗口实例后分配的额外字节数
    wndEx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); //窗口类背景画刷的句柄
    wndEx.hCursor = LoadCursor(NULL, IDC_ARROW); //窗口类光标的句柄
    wndEx.hIcon = LoadIcon(NULL, IDI_APPLICATION); //窗口类图标的句柄
    wndEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION); //窗口类图标的句柄
    wndEx.hInstance = hThis; //窗口过程的实例句柄
    wndEx.lpfnWndProc = WndProc; //指向窗口过程的指针
    wndEx.lpszClassName = TEXT("GUIProject"); //指向以空字符结尾的字符串或原子的指针
    wndEx.lpszMenuName = NULL; //指向以空字符结尾的字符串的指针,该字符串指定了窗口类菜单的资源名
    wndEx.style = CS_HREDRAW | CS_VREDRAW;

    if (!RegisterClassEx(&wndEx))
    {
        return -1;
    }

    HWND hWnd = CreateWindow( wndEx.lpszClassName, TEXT("GUI Project"), WS_OVERLAPPEDWINDOW,
                              200, 200, 400, 300, HWND_DESKTOP, NULL, hThis, 0);
    if (!hWnd)
    {
        return -1;
    }

    UpdateWindow(hWnd);

    ShowWindow(hWnd, iCmdShow); //设置指定窗口的显示状态
    MSG msg = { 0 }; //显示窗口消息

    while (GetMessage(&msg, NULL, NULL, NULL))
    {
        TranslateMessage(&msg); //把虚拟键消息翻译成字符消息
        DispatchMessage(&msg); //分发一条消息给窗口过程
    }

    DestroyWindow(hWnd);
    UnregisterClass(wndEx.lpszClassName, hThis); //注销窗口类,释放该类占用的内存
    return (int)msg.wParam; //从应用程序消息队列中返回一个成功推出代码或最后一个消息代码
}

//hWnd表示窗口标识,uMsg窗口消息代码(无符号整数),wParam和lParam传递应用程序定义的数据(64位长整型数)
//函数返回64位有符号长整型
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CLOSE:
    {
        PostQuitMessage(0); //释放系统资源,并安全关闭该应用程序
        break;
    }
    default:
    {
        //处理应用程序未处理的窗口信息,函数确保每个消息都被处理
        return DefWindowProc(hWnd, uMsg, wParam, lParam); //默认窗口过程
    }
    }
    return 0;
}

出现如下错误:

严重性 代码  说明  项目  文件  行   禁止显示状态
警告  C28251  “WinMain”的批注不一致: 此实例包含 无批注。请参见 c:\program files (x86)\windows kits\10\include\10.0.18362.0\um\winbase.h(933)。   GUIProject  C:\USERS\CDQ\SOURCE\REPOS\GUIPROJECT\GUIPROJECT\MAIN.CPP    6   

原因是建立的是控制台项目而不是win32项目,解决方法:

配置属性-->链接器-->系统-->子系统-->窗口,之后点击确定。

参考自:https://bbs.csdn.net/topics/392512424?list=63174050

二、解释进程模型

传统操作系统必须提供创建进程和终止进程的方法,下面列出4个引发创建进程的主要事件:

  1. 系统初始化;
  2. 正在运行的进程执行创建进程的系统调用;
  3. 用户要求创建新进程;
  4. 启动批处理工作。

创建一个打开Windows笔记本的进程:

#include <iostream>
#include<windows.h>
int main()
{
    std::cout << "Hello World!\n";

    STARTUPINFO startupinfo = { 0 };
    PROCESS_INFORMATION processInfomation = {0};
        //CreateProcess函数用于创建一个新进程和其主线程。
    BOOL bSucess = CreateProcess(TEXT("C:\\windows\\notepad.exe"), NULL, NULL, NULL, FALSE, NULL, NULL, NULL, &startupinfo, &processInfomation);
    if (bSucess)
    {
        std::cout << "Process started." << std::endl
            << "Process ID:\t" << processInfomation.dwProcessId << std::endl;
    }
    else
    {
        std::cout << "Cannont create process!" << std::endl
            << "Error code:\t" << GetLastError() << std::endl;
    }
    return system("pause");
}

终止进程的较好办法是调用ExtiProcess函数。

三、进程状态

运行:该进程正在使用CPU;
就绪:该进程可运行,但是没有CPU可用,还在排队等待其他进程放弃CPU的使用权;
阻塞:在某些外部事件发生前,该进程不能运行。


#include <iostream>
#include<windows.h>
//winternl包含了Windows内部函数大部分原型和数据类型
#include<winternl.h>

using std::cout;
using std::endl;

typedef NTSTATUS(WINAPI* QUERYINFORMATIONPROCESS)(
    HANDLE processHandle,
    PROCESSINFOCLASS processInformationClass,
    PVOID processInformation,
    ULONG processInformationLength,
    PULONG returnLength);

int main()
{
    std::cout << "Hello World!\n";

    STARTUPINFO startupinfo = { 0 };
    PROCESS_INFORMATION processInfomation = { 0 };

    BOOL bSuccess = CreateProcess(TEXT("C:\\windows\\notepad.exe"), NULL, NULL, NULL,
        FALSE, NULL, NULL, NULL, &startupinfo, &processInfomation);
    if (bSuccess)
    {
        std::cout << "Process started." << std::endl
            << "Process ID:\t" << processInfomation.dwProcessId << std::endl;

        PROCESS_BASIC_INFORMATION pbi;
        ULONG ulength = 0;

        HMODULE hDll = LoadLibrary(TEXT("C:\\windows\\System32\\ntdll.dll"));

        if (hDll)
        {
            QUERYINFORMATIONPROCESS QueryInformationProcess = (QUERYINFORMATIONPROCESS)GetProcAddress(hDll, "NtQueryInformationProcess");
            if (QueryInformationProcess)
            {
                NTSTATUS ntStatus = QueryInformationProcess(processInfomation.hProcess, PROCESSINFOCLASS::ProcessBasicInformation, &pbi, sizeof(pbi), &ulength);
                if (NT_SUCCESS(ntStatus))
                {
                    cout << "Process ID (from PCB):\t" << pbi.UniqueProcessId << endl;
                }
                else
                {
                    cout << "Cannot open PCB!" << endl
                        << "Error code:\t" << GetLastError() << endl;
                }
            }
            else
            {
                cout << "Cannot get NTQueryInformationProcess function!" << endl
                    << "Error code:\t" << GetLastError() << endl;
            }
            FreeLibrary(hDll);
        }
        else
        {
            cout << "Cannnot load ntdll.dll" << endl
                << "Error code:\t" << GetLastError() << endl;
        }
    }
    else
    {
        std::cout << "Cannont create process!" << std::endl
            << "Error code:\t" << GetLastError() << std::endl;
    }
    //CloseHandle(processInfomation.hProcess);
    //CloseHandle(processInfomation.hThread);
    return 0;
}
Hello World!
Process started.
Process ID:     11492
Process ID (from PCB):  11492

Windows多线程编程入门笔记的更多相关文章

  1. Windows多线程编程入门

    标签(空格分隔): Windows multithread programming 多线程 并发 编程 背景知识 在开始学习多线程编程之前,先来学习下进程和线程 进程 进程是指具有一定独立功能的程序在 ...

  2. 多线程编程学习笔记——async和await(三)

    接上文 多线程编程学习笔记——async和await(一) 接上文 多线程编程学习笔记——async和await(二) 五.   处理异步操作中的异常 本示例学习如何在异步函数中处理异常,学习如何对多 ...

  3. 多线程编程学习笔记——使用异步IO(一)

    接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...

  4. 多线程编程学习笔记——使用异步IO

    接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...

  5. C++Windows核心编程读书笔记

    转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...

  6. windows多线程编程星球(一)

    以前在学校的时候,多线程这一部分是属于那种充满好奇但是又感觉很难掌握的部分.原因嘛我觉得是这玩意儿和编程语言无关,主要和操作系统的有关,所以这部分内容主要出现在讲原理的操作系统书的某一章,看完原理是懂 ...

  7. 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

    Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)   介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...

  8. 多线程编程学习笔记——async和await(一)

    接上文 多线程编程学习笔记——任务并行库(一) 接上文 多线程编程学习笔记——任务并行库(二) 接上文 多线程编程学习笔记——任务并行库(三) 接上文 多线程编程学习笔记——任务并行库(四) 通过前面 ...

  9. 多线程编程学习笔记——async和await(二)

    接上文 多线程编程学习笔记——async和await(一) 三.   对连续的异步任务使用await操作符 本示例学习如何阅读有多个await方法方法时,程序的实际流程是怎么样的,理解await的异步 ...

随机推荐

  1. pandas.DataFrame.where和mask 解读

    1.前言背景 没怎么用过df.where 都是直接使用loc.apply等方法去解决. 可能是某些功能还没有超出loc和apply的适用范围. 2.进入df.where和df.mask DataFra ...

  2. Xilinx FFT IP核缩放因子说明

    以1024点FFT为例, reg [9:0] scale_sch = 10'b11_10_01_01_01; 流水线结构中,将每个基 2 的蝶形处理单元视为一个阶段. 每个阶段进行一次数据的缩减,缩减 ...

  3. html([val|fn])

    html([val|fn]) 概述 取得第一个匹配元素的html内容.这个函数不能用于XML文档.但可以用于XHTML文档.直线电机选型 在一个 HTML 文档中, 我们可以使用 .html() 方法 ...

  4. Linux shell -"a-d"命令

    shell中条件判断if中的-z到-d的意思 分类:shellLinux (2006)  (0) shell中条件判断if中的-z到-d的意思  [ -a FILE ] 如果 FILE 存在则为真.  ...

  5. 记一次 用 ssh 反向代理解决的远程操作效率问题

    公司在异地有一个项目,项目在内网有一个linux 集群开发人员通过 xshell 进行操作,但是开发过程中还需要公司开发人员进行远程操作,原来采用的方案是向日葵,需求能实现但是限于网络环境向日葵实在是 ...

  6. python sqlite3查询表记录

    1.查询数据库log_info表最后10条记录. desc - 指"降序" 解决的方法是:按照ID 逆序排列,选取前10个 select * from 'log_info' ord ...

  7. 浙江省赛C.Array in the Pocket(贪心+线段树)

    题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4102 题意: 给出一个长度为n的数组,重排它们,让相同位置的数 ...

  8. Dubbo API 笔记——Dubbo架构与使用

    转载于: https://blog.csdn.net/benhuo931115/article/details/78457149 架构演变 单一应用架构 所有功能部署在一个应用上,用于简化增删改查工作 ...

  9. LeetCode687----最长同值路径

    给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值. 这条路径可以经过也可以不经过根节点. 注意:两个节点之间的路径长度由它们之间的边数表示. 示例 1: 输入: 5 / \ 4 5 / ...

  10. Install chocolatey

    Requirements Windows 7+ / Windows Server 2003+ PowerShell v2+ .NET Framework 4+ (the installation wi ...