在工程线程中执行异步任务¶
Warning
The current page still doesn't have a translation for this language.
You can read it through google translate.
TaskLoop 简介¶
TaskLoop 是 SOUI 框架中的异步任务处理组件,它允许开发者将耗时操作放到后台线程中执行,避免阻塞 UI 线程,从而提升用户体验。
TaskLoop 核心接口¶
TaskLoop 组件的核心接口定义在 staskloop-i.h
文件中,主要包括两个结构体:
IRunnable 接口¶
IRunnable 是任务执行的基本接口,定义了任务对象需要实现的方法:
struct IRunnable
{
virtual ~IRunnable() {}
virtual IRunnable* clone() const = 0;
virtual void run() = 0;
virtual void *getObject() = 0;
virtual const char *getClassInfo() const = 0;
};
各方法说明: - clone()
:克隆当前任务对象 - run()
:执行任务逻辑 - getObject()
:获取任务关联的对象 - getClassInfo()
:获取任务类信息
ITaskLoop 接口¶
ITaskLoop 是任务循环的核心接口,提供了任务管理的各种方法:
struct ITaskLoop : public IObjRef
{
// 任务优先级枚举
enum Priority
{
High = 1, // 高优先级
Normal = 0, // 普通优先级
Low = -1, // 低优先级
};
/**
* @brief 获取任务循环名称
* @param pszBuf 缓冲区
* @param nBufLen 缓冲区长度
* @return 是否获取成功
*/
virtual bool getName(char *pszBuf, int nBufLen) = 0;
/**
* @brief 启动任务循环线程
* @param pszName 线程名称
* @param priority 线程优先级
*/
virtual void start(const char * pszName, Priority priority) = 0;
/**
* @brief 同步停止线程
*/
virtual void stop() = 0;
/**
* @brief 提交任务到任务管理器
* @param runnable 要运行的任务对象
* @param waitUntilDone true 表示同步等待,false 表示异步提交
* @param priority 任务优先级
* @return 任务 ID,可用于取消任务
*/
virtual long postTask(const IRunnable *runnable, bool waitUntilDone, int priority=0) = 0;
/**
* @brief 移除指定对象的所有待处理任务
* @param object 指定对象
*/
virtual void cancelTasksForObject(void *object) = 0;
/**
* @brief 取消指定 ID 的任务
* @param taskId 任务 ID
* @return 是否取消成功
*/
virtual bool cancelTask(long taskId) = 0;
/**
* @brief 获取任务队列中的任务总数
* @return 任务总数
*/
virtual int getTaskCount() const = 0;
/**
* @brief 获取运行状态
* @return 是否正在运行
*/
virtual bool isRunning() = 0;
/**
* @brief 获取正在运行的任务信息
* @param buf 接收任务信息的缓冲区
* @param bufLen 缓冲区长度
* @return false - 没有任务正在运行; true - 获取成功
*/
virtual bool getRunningTaskInfo(char *buf, int bufLen) = 0;
};
使用方法¶
使用 TaskLoop 组件需要以下步骤:
1. 组件编译与创建¶
首先需要完成 TaskLoop 组件的编译,然后通过 SComMgr 来创建 TaskLoop 对象:
// 创建 TaskLoop 对象
CAutoRefPtr<ITaskLoop> pTaskLoop;
if (pComMgr->CreateTaskLoop((IObjRef**)&pTaskLoop))
{
// 成功创建 TaskLoop 对象
}
2. 启动任务循环¶
创建 TaskLoop 对象后,需要调用 start
方法启动任务循环:
// 启动任务循环,名称为 "test",优先级为低
pTaskLoop->start("test", ITaskLoop::Low);
3. 提交任务¶
使用 postTask
方法提交任务到任务循环中:
// 提交任务
pTaskLoop->postTask(runnable, false, 0);
4. 停止任务循环¶
任务完成后,调用 stop
方法停止任务循环:
// 停止任务循环
pTaskLoop->stop();
任务优先级¶
TaskLoop 支持任务优先级管理:
- 默认优先级为 0(Normal)
- 可设置优先级为 High(1)、Normal(0)、Low(-1)
- 任务插入队列时会根据优先级自动排序,优先级越大越靠前执行
任务创建辅助工具¶
SOUI 提供了 sfunctor.hpp
辅助头文件,可以方便地将对象的成员函数或全局函数转换为 IRunnable 对象。
使用示例¶
以下是一个完整的 TaskLoop 使用示例:
// 演示异步任务处理类
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 图片解码模块
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;
}
最佳实践¶
-
结合 NotifyCenter 使用:在异步任务中需要通知 UI 层时,最好结合 SOUI 的 NotifyCenter 对象一起使用,这是最简单有效的方式。
-
合理设置优先级:根据任务的重要性和紧急程度合理设置任务优先级。
-
及时释放资源:任务完成后及时调用
stop
方法停止任务循环,释放相关资源。 -
错误处理:在实际应用中,需要添加适当的错误处理机制,确保程序的稳定性。
参考示例¶
更多使用示例可以参考 SOUI 的壁纸示例项目:demos/SouiWallPaper
通过合理使用 TaskLoop 组件,可以有效提升 SOUI 应用的性能和用户体验,特别是在处理网络请求、文件操作等耗时任务时。