代碼中頻繁出現下面描述的模式,
某些操做調用服務端接口獲取數據、執行復雜的數據解析,這些操做不能阻塞UI線程,必須異步執行,但一般這些操做執行完後須要對界面元素進行更新。
就是這麼個模式在代碼中頻繁出現。
以前代碼解決此問題的方式是使用thread,通常流程是下面這樣(工做任務通常在模型中有封裝,這些操做是阻塞的),
程序員
1. 首先咱們必須把這些接口封裝成thread要求的接口,一般使用內部類(以前咱們用的是VS05版本,沒有lambda)算法
2. 調用boost::thread數組
3. 執行完後PostMessage到某個窗體異步
4. 修改該窗體代碼,加上消息捕獲和消息處理方法函數
5. 等(取決想要什麼額外操做和程序員的寫法)post
使用過相似方法的都知道有多痛苦,想寫的心都沒了,有時所以還會偷懶,好比在異步中更新界面元素。
一般上面說的每一步都是很短小且用一次的代碼,但使用上面的方式必須把小短的代碼分散到不一樣的源文件中,增長了對象間的引用交互,最主要的是麻煩,每次須要執行該模式時,執行上面的每一步都是痛苦的。
想要的其實很簡單:異步執行指定的動做,等執行完後記得更新界面元素。
既然是頻繁出現的模式,那就把該模式封裝起來,接口中只需填寫
1. 須要執行什麼動做
2. 如何更新界面元素
參照C#中的then,咱們最終要的大概是以下寫法,
aync([=]()->DWORD_PTR {
std::string result;
m_impl->user->getCrashResult(begin->first, result);
return CrashResult::GetResultCount(result);
}).then([=](DWORD_PTR result) {
UpdateCrashResult(unsigned int)begin->first.fileId(), (int)result);
});
aync中的代碼在工做線程中執行,then中的代碼在UI線程中執行(如今VS版本是VS10,有lambda支持)。
實現想法以下,
aync內部會把lambda以及then中的行爲封裝爲對象,存儲到一個數組中,aync要求的接口是返回DWORD_PTR類型的無參函數,返回的值在then中做爲參數,DWORD_PTR就是一個int型,說是指針也好,這東西在Windows平臺傳參很常見,我的很喜歡這個,由於用法很靈活。
aync中會把lambda轉換成無參無返回值類型,以適應thread接口,以後放入線程池中,
BimWorks::GetAsyncAction().Append([&]() {
this->result_ = func_();
GetBWAsyncInvoke().Submit(*this);
});
在func_執行完後調用 GetBWAsyncInvoke().Submit(*this); 該方法執行post消息到主線程動做,這裏使用一個隱藏的static窗體做爲消息的接收方。
消息處理函數簡單的從隊列中找到該lambda對應的對象,執行保存的then動做。執行完後從隊列中移除該對象。
完成。
這個實現只是一個初步的方法,有些細節須要完善的。
這種方式只適用一種固定的模式,即最開始描述的模式,thread太底層了,咱們每每須要更高層的模式,好比task這樣的概念,VS10中的PPL庫提供了其它一些模式,好比task,並行算法、容器,流水線,協做等,感受都不是咱們想要的這種很是輕量的寫法。this