SOUI中TaskLoop组件介绍

SOUI是一套开源(MIT协议)的Windows平台下的DirectUI框架,它提供了大量的高效控件,也提供了很多扩展组件,目前已经持续维护近10年,在大量的项目中证明稳定可靠。

GIT地址:

国内:https://gitee.com/setoutsoft/soui

国外:https://github.com/soui2/soui

 

下面介绍一个最近增加的组件:TaskLoop.

TaskLoop是一个异步任务模块。对于有网络请求的情况,异步任务是常规需求。

和使用其它SOUI组件一样,要使用异步任务模块,先完成组件的编译,然后就可以通过SComMgr来创建TaskLoop对象。

 

打开soui.08.sln可以看到上面工程组织结构。使用其它版本VS的朋友,可以用build.bat来生成自己需要的VS版本。

我们先看一看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对象中的任务顺序在同一个线程中执行。

任务的优先级默认是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

posted @ 2019-02-03 11:22  启程软件  阅读(1695)  评论(0编辑  收藏  举报