SOUI是一套開源(MIT協議)的Windows平臺下的DirectUI框架,它提供了大量的高效控件,也提供了不少擴展組件,目前已經持續維護近10年,在大量的項目中證實穩定可靠。git
GIT地址:github
國內:https://gitee.com/setoutsoft/soui網絡
國外:https://github.com/soui2/soui框架
下面介紹一個最近增長的組件:TaskLoop.異步
TaskLoop是一個異步任務模塊。對於有網絡請求的狀況,異步任務是常規需求。函數
和使用其它SOUI組件同樣,要使用異步任務模塊,先完成組件的編譯,而後就能夠經過SComMgr來建立TaskLoop對象。oop
打開soui.08.sln能夠看到上面工程組織結構。使用其它版本VS的朋友,能夠用build.bat來生成本身須要的VS版本。post
咱們先看一看staskloop-i.h中的接口定義。動畫
1 #pragma once 2 #include <unknown/obj-ref-i.h> 3 4 namespace SOUI 5 { 6 struct IRunnable 7 { 8 virtual ~IRunnable() {} 9 virtual IRunnable* clone() const = 0; 10 virtual void run() = 0; 11 virtual void *getObject() = 0; 12 virtual const char *getClassInfo() const = 0; 13 }; 14 15 struct ITaskLoop : public IObjRef 16 { 17 enum Priority 18 { 19 High = 1, 20 Normal = 0, 21 Low = -1, 22 }; 23 24 virtual bool getName(char *pszBuf, int nBufLen) = 0; 25 26 /** 27 * Start a thread to run. 28 * @param priority the thread priority 29 */ 30 virtual void start(const char * pszName,Priority priority) = 0; 31 32 /** 33 * Stop thread synchronized. 34 */ 35 virtual void stop() = 0; 36 37 /** 38 * postTask post or send a tasks to this task manager. 39 * @param runnable the to be run task object. 40 * @param waitUntilDone, true for send and false for post. 41 * @param priority, the task priority. 42 * @return the task id, can be used by cancelTask. 43 */ 44 virtual long postTask(const IRunnable *runnable, bool waitUntilDone, int priority=0) = 0; 45 46 /** 47 * Remove tasks for a specific object from task loop pending task list 48 * @param object the specific object wants pending functors to be removed 49 */ 50 virtual void cancelTasksForObject(void *object) = 0; 51 52 /** 53 * Cancel tasks for a specific task ID list 54 * @param taskList the task ID list to be canceled 55 * @return the removed task list. 56 */ 57 virtual bool cancelTask(long taskId) = 0; 58 59 /** 60 * get the total task number in the task loop queue. 61 * @return total task number in task loop queue 62 */ 63 virtual int getTaskCount() const = 0; 64 65 /** 66 * get the run loop status. 67 * @return the running status 68 */ 69 virtual bool isRunning() = 0; 70 71 /** 72 * get the running task info. 73 * @param buf, to receive task info buf. 74 * @param bufLen, buffer length 75 * @return false - no task is running; true - succeed. 76 */ 77 virtual bool getRunningTaskInfo(char *buf, int bufLen) = 0; 78 }; 79 }
建立出ITaskLoop接口後,先調用start來啓動,再調用postTask來添加一個異步任務。添加到同一個TaskLoop對象中的任務順序在同一個線程中執行。ui
任務的優先級默認是0,若是不少任務在排除,新加入的任務但願優先執行,則將nPriority這個參數設置爲一個更大的值,任務插入隊列的時候,自動根據nPriority排序,nPriority越大,排序越前。
postTask須要提供一個IRunnable對象來運行。
使用SOUI/helper/sfunctor.hpp能夠方便的將一個對象的成員函數或者全局函數轉換成爲一個IRunnable對象。
下面看一下demo中如何使用ITaskLoop.
//演示異步任務。 class CAsyncTaskObj { public: void task1(int a) { SLOG_INFO("task1,a:" << a); } void task2(int a, const std::string & b) { SLOG_INFO("task2,a:" << a<<" b:"<<b.c_str()); } }; int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/) { //必需要調用OleInitialize來初始化運行環境 HRESULT hRes = OleInitialize(NULL); SASSERT(SUCCEEDED(hRes)); //使用imgdecoder-png圖片解碼模塊演示apng動畫 SComMgr2 *pComMgr = new SComMgr2(_T("imgdecoder-png")); { //演示異步任務。 CAutoRefPtr<ITaskLoop> pTaskLoop; if (pComMgr->CreateTaskLoop((IObjRef**)&pTaskLoop)) { CAsyncTaskObj obj; pTaskLoop->start("test", ITaskLoop::Low); STaskHelper::post(pTaskLoop, &obj, &CAsyncTaskObj::task1, 100,true); STaskHelper::post(pTaskLoop, &obj, &CAsyncTaskObj::task2, 100,"abc", true); pTaskLoop->stop(); pTaskLoop = NULL; } } //.... return 0; }
注:
demo爲了方便演示其實是在工做線程中使用了同步等待。
使用TaskLoop最好結合SOUI的NotifyCenter對象一塊兒使用,在異步任務中須要通知UI層,使用NotifyCenter是最簡單有效的。
更多用法參考SOUI的壁紙demo: https://github.com/soui-demo/SouiWallPaper
啓程軟件 2019-02-03