程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 異步更新界面方法

異步更新界面方法

編輯:C++入門知識

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

某些操作調用服務端接口獲取數據、執行復雜的數據解析,這些操作不能阻塞UI線程,必須異步執行,但通常這些操作執行完後需要對界面元素進行更新。

就是這麼個模式在代碼中頻繁出現。

之前代碼解決此問題的方式是使用thread,一般流程是下面這樣(工作任務一般在模型中有封裝,這些操作是阻塞的),

   1.  首先我們必須把這些接口封裝成thread要求的接口,通常使用內部類(之前我們用的是VS05版本,沒有lambda)

   2.  調用boost::thread

   3.  執行完後PostMessage到某個窗體

   4. 修改該窗體代碼,加上消息捕獲和消息處理方法

   5. 等(取決想要什麼額外操作和程序員的寫法)


使用過類似方法的都知道有多痛苦,想寫的心都沒了,有時因此還會偷懶,比如在異步中更新界面元素。

通常上面說的每一步都是很短小且用一次的代碼,但使用上面的方式必須把小短的代碼分散到不同的源文件中,增加了對象間的引用交互,最主要的是麻煩,每次需要執行該模式時,執行上面的每一步都是痛苦的。

想要的其實很簡單:異步執行指定的動作,等執行完後記得更新界面元素。

既然是頻繁出現的模式,那就把該模式封裝起來,接口中只需填寫

   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,並行算法、容器,流水線,協作等,感覺都不是我們想要的這種非常輕量的寫法。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved