C++线程的创建

C/C++ 同时被 2 个专栏收录
65 篇文章 1 订阅
13 篇文章 2 订阅

前言

线程创建很容易,直接调用std::thread,就创建一个新线程了。该线程拿到任务后立即开始执行。
线程的创建者(父线程)必须管理创建的线程(子线程),应该等到子线程完成其任务或者让子线程从自己身上脱离。子线程可以通过复制或引用获取任务执行的参数。


创建和执行线程

现在,更正式的方法创建线程:一个线程获得一个Callable后立即启动它。

Callable是一个行为类似于一个函数的实体。它可以是一个函数,一个函数对象或lambda函数。
函数对象是类的实例,调用操作符()被重载。函数和函数对象之间的关键区别在于,函数对象可以具有状态。
lambda函数(匿名函数)是一个纯函数体,没有名字。它可以在适当的位置调用。lambda函数可以捕获它的调用上下文。这就是为什么他们经常被称为闭包。


不废话了,看个例子吧:

// createThread.cpp

#include <iostream>
#include <thread>

void helloFunction() 
{
    std::cout << "Hello C++11 from function." << std::endl;
}

class HelloFunctionObject 
{
public:
    void operator()() const 
    {
        std::cout << "Hello C++11 from a function object." << std::endl;
    }
};

int main() {
    std::cout << std::endl;

    // 线程执行函数 helloFunction
    std::thread t1(helloFunction);

    // 线程执行函数对象 helloFunctionObject
    HelloFunctionObject helloFunctionObject;
    std::thread t2(helloFunctionObject);

    // 线程执行 lambda function
    std::thread t3([] 
    {
        std::cout << "Hello C++11 from lambda function." << std::endl; 
    });

    // 确保 t1, t2 and t3 在main函数结束之前结束
    t1.join();
    t2.join();
    t3.join();

    std::cout << std::endl;
};

所有线程t1、t2和t3将它们的输出写入控制台。
线程t2的工作包任务是一个函数对象,线程t3的工作包任务是lambda函数。
主线程或父进程等待,直到它的子线程完成为止。
让我们看一下输出:
这里写图片描述
这两个程序的执行结果在两个方面有所不同。首先,子线程将以不同的顺序执行。其次,输出有点乱。因此,在第二次运行中,函数helloFunction的换行符发生在lambda函数调用之后。


原文地址:

http://www.modernescpp.com/index.php/thread-creation
  • 5
    点赞
  • 1
    评论
  • 16
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

1. 创建一个基于对话框应用程序。并增加如图所示控件;分别为3个进度条控件关联三个进度条类型变量;并在对话框初始化函数中,设定进度条范围;为编辑框关联一个整型变量;为12个按钮添加消息处理函数; 2. 定义结构体:用做线程函数参数传递 typedef struct Threadinfo{ CProgressCtrl *progress;//进度条对象 int speed; //进度条速度 int pos; //进度条位置 } thread,*lpthread; 3. 为对话框增加三个句柄,用于标识各个线程; HANDLE hThread1; //线程1线程句柄 HANDLE hThread2; //线程2线程句柄 HANDLE hThread3; //线程3线程句柄 在增加三个结构体类型变量,用做线程函数参数传递; HANDLE hThread1; //线程1线程句柄 HANDLE hThread2; //线程2线程句柄 HANDLE hThread3; //线程3线程句柄 4. 新增一个静态全局变量,用于记录所有线程状态:static int GlobalVar=10000; 5. 声明并编写线程函数,注意只能有一个参数,且函数返回值类型也是固定;函数名可以自定义; DWORD WINAPI ThreadFun(LPVOID pthread);//线程入口函数 6. 在启动按钮消息处理函数中编写如下代码: thread1.progress=&m_progress1;//进度条对象 thread1.speed=100;//速度 thread1.pos=0;//初始位置 hThread1=CreateThread(NULL,0,ThreadFun,&thread1;,0,0);//创建并开始线程 if (!hThread1) { MessageBox("创建线程失败"); } 7. 编写线程函数(一般是一个死循环,或者需要花费时间很长算法!否者就失去了多线程意义) DWORD WINAPI ThreadFun(LPVOID pthread) //线程入口函数 { lpthread temp=(lpthread)pthread;//参数强制转换为结构体类型 temp->progress->SetPos(temp->pos); //设置被传递过来进度条位置 while(temp->posspeed); /设置速度 temp->pos++; //增加进度 temp->progress->SetPos(temp->pos); //设置进度条新位置 GlobalVar--; if(temp->pos==20) { temp->pos=0; //进度条满则归0 } } return true; } 8. 在挂起按钮函数中,编写如下代码: if(SuspendThread(hThread1)==0xFFFFFFFF) { MessageBox("挂起失败!进程可能已经死亡或未创建!"); return; } 9. 在执行按钮函数中,编写如下代码: if(ResumeThread(hThread1)==0xFFFFFFFF) { MessageBox("执行失败!进程可能已经死亡或未创建!"); return; } 10. 在停止按钮函数中,编写如下代码: if(TerminateThread(hThread1,0))//前些终止线程 { CloseHandle(hThread1);//销毁线程句柄 } else { MessageBox("终止进程失败!"); } 11. 为应用程序添加WM_TIMER消息,实时更新全局变量值到编辑框;
相关推荐
©️2020 CSDN 皮肤主题: 程序猿惹谁了 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值