• 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

  • 相关阅读:
    2019前端面试系列——CSS面试题
    面试题——数组转树结构
    前端安全
    webpack入门——构建简易版vue-cli
    [] == ![],走进==隐式转换的世界
    Vue图片懒加载插件
    JS常用时间处理方法
    Vue中实现token验证
    VSCode基本配置
    打乱数组——shuffle
  • 原文地址:https://www.cnblogs.com/setoutsoft/p/10349942.html
Copyright © 2020-2023  润新知