每次处理并行任务时,如果要等待用户输入或依赖外部(如与灿亨控制器响应),就应该为类似的操作单独创建一个线程,这样我们的程序才不会挂起无响应。
静态库和动态库
静态库是指在程序运行前就编译完成的库,如#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. 利用vue v-bind属性绑定bootstrap样式以及输出数据

    自从知道了bootstrap,就被他简介,大气美观的样式吸引,即使在vue框架中,仍旧想使用,下面给出了vue适配版和原版的代码,以飨读者 数据输出部分 export default { data() ...

  2. parent([expr]) 取得一个包含着所有匹配元素的唯一父元素的元素集合。

    parent([expr]) 概述 取得一个包含着所有匹配元素的唯一父元素的元素集合.大理石构件 你可以使用可选的表达式来筛选. 参数 exprStringV1.0 用来筛选的表达式 示例 描述: 查 ...

  3. BZOJ 2346: [Baltic 2011]Lamp Dijkstra

    不难发现如果一个边的方向改变,就一定不会改回来(这样肯定不是最短路). 所以就直接建双向边,边权为 $0$ 代表不改变,边权为 $1$ 代表改变,跑一个最短路即可. #include <bits ...

  4. cropbox.js 头像裁剪插件

    cropbox.js 一个轻量级和简单的JavaScript,Jquery,YUI插件来裁剪您的头像. 特征 支持dataUrl显示图像(函数getDataURL) 支持Blob上传图片(函数getB ...

  5. [vim]多行注释和多行删除

    vim中多行注释和多行删除命令,这些命令也是经常用到的一些小技巧,可以大大提高工作效率. 1.多行注释: 首先按esc进入命令行模式下,按下Ctrl + v,进入列(也叫区块)模式; 在行首使用上下键 ...

  6. Java中基本数据类型

    在数据类型中,最常用也是最基础的数据类型,被称作基本数据类型.可以使用这些类型的值来代表一些简单的状态. Java 语言的基本数据类型总共有以下8 种,下面是按照用途划分出的4 个类别: 定点类型: ...

  7. 完全免费,再也不用担心转pdf文件乱来乱去的问题了

    完全免费,再也不用担心转pdf文件乱来乱去的问题了. 源代码:https://github.com/xlgwr/WpsToPdf.git 第三方插件Bye Bye... 功能说明 主要引用Wps金山办 ...

  8. LVS之DR模式

    目录: 网络环境 LVS服务器网络配置 LVS服务器添加ipvs规则 RS服务器配置 访问验证 抓包分析 注意事项 [网络环境] 网络拓扑结构如下表: 服务器 类型 网卡 IP MAC 说明 v_me ...

  9. 外网访问内网的FTP服务器

    转自 外网访问内网的FTP服务器 首先感谢作者给出的总结,原文是介绍Serv-U的,我针对FileZilla Server进行了稍微修改,仅看操作可直接跳到分割线后第3部分. 1. 背景简介最近研究如 ...

  10. 解决spring-boot 各版本包冲突兼容的方法

    思路        在微服务盛行的当下,spring boot 流行程度已经家喻户晓.但同时,随着spring boot 快速迭代,出现了很多版本,比如当前已经推出了2.2.x-SNAPSHOT/ , ...