使用C++11的thread取代QThread

  因为在做的工程项目里使用了Qt,而实际上不涉及到屏幕显示,工程代码里使用了QThread,且没有使用Qt核心的信号与槽,为了以后移植准备使用更加通用的C++11 stl中的thread取代QThread。

  下面是一些测试过程,因为没有为这个小测试建一个版本控制,所以为了能记录每步测试修改,这里将编写代码编写博客,开始吧。

 1 #include <iostream>
 2 #include <thread>
 3 #include <chrono>
 4 #include <functional>
 5 
 6 using namespace std;
 7 
 8 class MyThread
 9 {
10 public:
11     MyThread()
12     {
13         thread t([this]()-> void {
14             
15             run();
16 
17         });
18         t.detach();
19     }
20 
21 public:
22     void run()
23     {
24         for(int i=0;i<5;i++)
25         {
26                     cout<<"Hello Nelson!"<<endl;
27             std::this_thread::sleep_for(std::chrono::milliseconds(1000));
28         }
29     }
30 };
31 
32 int main(int argc,char *argv[])
33 {
34 
35     MyThread mythread;
36 
37     cout<<"main thread is over"<<endl;
38 
39     return 0;
40 }
View Code

  上面代码运行环境,Ubuntu 16.04.4  g++版本:gcc version 5.4.0

  先使用VS2008编译不行,VS2010编译不行,主要报错是说没有std::thread,这里有个文档,里面有VS各个版本对C++11支持说明,https://blogs.msdn.microsoft.com/vcblog/2011/09/12/c11-features-in-visual-c-11/  (C++11 Features in Visual C++11)。

  上述代码的编译指令是这样的:g++ -std=c++11 -pthread test.cpp -o test        

  注意指定标准C++11和-pthread线程库链接选项,test.c代码里没有#include <pthread> ,如果去掉-phtread编译,结果提示undefined reference to `pthread_create'。运行test,结果如下:

  

  子线程建立后,主线程和子线程的线程调度是不确定的,索引多执行几次test后,结果会不一样。因为thread对象调用了detach,所以子线程运行状态与线程对象完全无关,thread t在构造函数执行完了之后就消亡了。如果验证子线程在主线程结束了以后还在运行呢?在子线程里向文件里写内容。

#include <iostream>
#include <thread>
#include <chrono>
#include <functional>
#include <fstream>

using namespace std;

class MyThread
{
public:
    MyThread()
    {
        thread t([this]()-> void {
            
            run();

        });
        t.detach();
    }

public:
    void run()
    {
        fstream f;
        f.open("test.txt",ios::out|ios::trunc);

        for(int i=0;i<5;i++)
        {
                    cout<<"Hello Nelson!"<<endl;
            f<<"Write One Line
";
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            f<<"Write The Other Line
";
        }
        f.close();
    }
};

int main(int argc,char *argv[])
{

    MyThread mythread;

    cout<<"main thread is over"<<endl;

    std::this_thread::sleep_for(std::chrono::milliseconds(10));  //delay for file create

    return 0;
}
View Code

  编译运行,结果如下:

  

  和想象中的结果不一致,预期是子线程独立运行,在文档中写入多行文字,而且结果中居然一行也没有显示。修改主线程休眠时间,由10ms改为10s,结果如下:

  

  这就说明文件读写是很正常的。

  主线程关闭时也关闭了子线程?不然无法理解Hello Nelson不接着打印,同时文件写操作内容不见了。文件写操作内容不见了则可以说明这种情况下,子线程内部的操作都是不安全的,不可预期的。

  下面测试让主线程主动关闭子线程(通过控制变量bRun做到的),这才是需要的线程基本控制。

 1 #include <iostream>
 2 #include <thread>
 3 #include <chrono>
 4 #include <functional>
 5 #include <fstream>
 6 
 7 using namespace std;
 8 
 9 class MyThread
10 {    
11 private:
12     bool bRun;
13 
14 public:
15     void DisableThreadRun()
16     {
17         bRun = false;
18     }
19 
20 public:
21     MyThread()
22     {
23         bRun = true;
24 
25         thread t([this]()-> void {
26             
27             run();
28 
29         });
30         t.detach();
31     }
32 
33 public:
34     void run()
35     {
36         fstream f;
37         f.open("test.txt",ios::out|ios::trunc);
38 
39         while(bRun)
40         {    
41             for(int i=0;i<5;i++)
42             {
43                         cout<<"Hello Nelson!"<<endl;
44                 f<<"Write One Line
";
45                 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
46                 f<<"Write The Other Line
";
47             }
48             f.flush();
49         }
50         f.close();
51         cout<<"sub thread is running out"<<endl;
52     }
53 };
54 
55 int main(int argc,char *argv[])
56 {
57     MyThread mythread;
58 
59     std::this_thread::sleep_for(std::chrono::milliseconds(10000));  //delay for file create
60     mythread.DisableThreadRun();
61     std::this_thread::sleep_for(std::chrono::milliseconds(2000));
62 
63     cout<<"main thread is over"<<endl;
64 
65     return 0;
66 }
View Code

  测试结果如下

  

  主要是子线程函数,这里使用lambda表达式用起来就是非常的爽,【capture】属性中填入this(参见上一篇博客),lambda表达式中就可以获得所在类里的所有权限了,直接调用类成员方法run。开起来是不是跟QThread里的Run一样。

    使用C++11的thread去掉QThread很容易了吧。

原文地址:https://www.cnblogs.com/kanite/p/8417642.html