使用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\n";
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            f<<"Write The Other Line\n";
        }
        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\n";
45                 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
46                 f<<"Write The Other Line\n";
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很容易了吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM