Windows多线程编程入门笔记
每次处理并行任务时,如果要等待用户输入或依赖外部(如与灿亨控制器响应),就应该为类似的操作单独创建一个线程,这样我们的程序才不会挂起无响应。
静态库和动态库
静态库是指在程序运行前就编译完成的库,如#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个引发创建进程的主要事件:
- 系统初始化;
- 正在运行的进程执行创建进程的系统调用;
- 用户要求创建新进程;
- 启动批处理工作。
创建一个打开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多线程编程入门笔记的更多相关文章
- Windows多线程编程入门
标签(空格分隔): Windows multithread programming 多线程 并发 编程 背景知识 在开始学习多线程编程之前,先来学习下进程和线程 进程 进程是指具有一定独立功能的程序在 ...
- 多线程编程学习笔记——async和await(三)
接上文 多线程编程学习笔记——async和await(一) 接上文 多线程编程学习笔记——async和await(二) 五. 处理异步操作中的异常 本示例学习如何在异步函数中处理异常,学习如何对多 ...
- 多线程编程学习笔记——使用异步IO(一)
接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...
- 多线程编程学习笔记——使用异步IO
接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...
- C++Windows核心编程读书笔记
转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...
- windows多线程编程星球(一)
以前在学校的时候,多线程这一部分是属于那种充满好奇但是又感觉很难掌握的部分.原因嘛我觉得是这玩意儿和编程语言无关,主要和操作系统的有关,所以这部分内容主要出现在讲原理的操作系统书的某一章,看完原理是懂 ...
- 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)
Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...
- 多线程编程学习笔记——async和await(一)
接上文 多线程编程学习笔记——任务并行库(一) 接上文 多线程编程学习笔记——任务并行库(二) 接上文 多线程编程学习笔记——任务并行库(三) 接上文 多线程编程学习笔记——任务并行库(四) 通过前面 ...
- 多线程编程学习笔记——async和await(二)
接上文 多线程编程学习笔记——async和await(一) 三. 对连续的异步任务使用await操作符 本示例学习如何阅读有多个await方法方法时,程序的实际流程是怎么样的,理解await的异步 ...
随机推荐
- 利用vue v-bind属性绑定bootstrap样式以及输出数据
自从知道了bootstrap,就被他简介,大气美观的样式吸引,即使在vue框架中,仍旧想使用,下面给出了vue适配版和原版的代码,以飨读者 数据输出部分 export default { data() ...
- parent([expr]) 取得一个包含着所有匹配元素的唯一父元素的元素集合。
parent([expr]) 概述 取得一个包含着所有匹配元素的唯一父元素的元素集合.大理石构件 你可以使用可选的表达式来筛选. 参数 exprStringV1.0 用来筛选的表达式 示例 描述: 查 ...
- BZOJ 2346: [Baltic 2011]Lamp Dijkstra
不难发现如果一个边的方向改变,就一定不会改回来(这样肯定不是最短路). 所以就直接建双向边,边权为 $0$ 代表不改变,边权为 $1$ 代表改变,跑一个最短路即可. #include <bits ...
- cropbox.js 头像裁剪插件
cropbox.js 一个轻量级和简单的JavaScript,Jquery,YUI插件来裁剪您的头像. 特征 支持dataUrl显示图像(函数getDataURL) 支持Blob上传图片(函数getB ...
- [vim]多行注释和多行删除
vim中多行注释和多行删除命令,这些命令也是经常用到的一些小技巧,可以大大提高工作效率. 1.多行注释: 首先按esc进入命令行模式下,按下Ctrl + v,进入列(也叫区块)模式; 在行首使用上下键 ...
- Java中基本数据类型
在数据类型中,最常用也是最基础的数据类型,被称作基本数据类型.可以使用这些类型的值来代表一些简单的状态. Java 语言的基本数据类型总共有以下8 种,下面是按照用途划分出的4 个类别: 定点类型: ...
- 完全免费,再也不用担心转pdf文件乱来乱去的问题了
完全免费,再也不用担心转pdf文件乱来乱去的问题了. 源代码:https://github.com/xlgwr/WpsToPdf.git 第三方插件Bye Bye... 功能说明 主要引用Wps金山办 ...
- LVS之DR模式
目录: 网络环境 LVS服务器网络配置 LVS服务器添加ipvs规则 RS服务器配置 访问验证 抓包分析 注意事项 [网络环境] 网络拓扑结构如下表: 服务器 类型 网卡 IP MAC 说明 v_me ...
- 外网访问内网的FTP服务器
转自 外网访问内网的FTP服务器 首先感谢作者给出的总结,原文是介绍Serv-U的,我针对FileZilla Server进行了稍微修改,仅看操作可直接跳到分割线后第3部分. 1. 背景简介最近研究如 ...
- 解决spring-boot 各版本包冲突兼容的方法
思路 在微服务盛行的当下,spring boot 流行程度已经家喻户晓.但同时,随着spring boot 快速迭代,出现了很多版本,比如当前已经推出了2.2.x-SNAPSHOT/ , ...