每次处理并行任务时,如果要等待用户输入或依赖外部(如与灿亨控制器响应),就应该为类似的操作单独创建一个线程,这样我们的程序才不会挂起无响应。
静态库和动态库
静态库是指在程序运行前就编译完成的库,如#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. windows下C语言头文件的运用

    头文件 singnext.dingswords printf("终止我每丝呼吸,让心灵穿透所有的秘密\n"); 头文件 singtocj.h printf("当无数的日月 ...

  2. 1 Java面向对象

    0 工具 在分析面向对象时最好采用UML图进行分析设计 1 Java面向对象的特点 java采用面向对象的方法设计程序主要体现在:对象有属性和方法,事件的发生是对象间的信息交互产生的即程序中的get ...

  3. PHP mysqli_get_charset() 函数

    mysqli_get_charset() 函数返回字符集对象. <?php $con=mysqli_connect("localhost","my_user&quo ...

  4. 在gitlab上删除分支后,本地git branch -r还能看到

    1. git remote prune --dry-run origin 查看当前有哪些是该消失还存在的分支 2. git remote prune origin 删除上面展示的所有分支 3. git ...

  5. Vue + Vuex 简单使用

    我们要实现的很简单,就是点击+1的count加一,点击-1的时候count-1 一.mutation 在vue 中,只有mutation 才能改变state.  mutation 类似事件,每一个mu ...

  6. 小米oj 帮小学生排队(排序+插入)

     帮小学生排队 序号:#18难度:有挑战时间限制:1000ms内存限制:10M 描述 用一个数组表示一群正在排队的小学生,每个小学生用一对整数 H, K 来表示:H 表示这个小学生的身高,K 表示这个 ...

  7. 微信公众号【黄小斜】和【Java技术江湖】

  8. FreeMarker学习(常用指令)

    参考:http://freemarker.foofun.cn/dgui_quickstart_basics.html assign: 使用该指令你可以创建一个新的变量, 或者替换一个已经存在的变量 a ...

  9. 微信小程序 保存图片

    微信小程序 保存图片 注: 此处使用的是小程序 wepy框架, 原生或其他的请注意转换写法 <div class="handle"> <button class= ...

  10. PHP遍历目录下的文件夹和文件 以及遍历文件下内容

    1.遍历目录下的文件夹和文件: public function bianli1($dir) { $files = array(); if($head = opendir($dir)) { while( ...