異步更新界面方法

代碼中頻繁出現下面描述的模式,

某些操做調用服務端接口獲取數據、執行復雜的數據解析,這些操做不能阻塞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

相關文章
相關標籤/搜索