AsyncRequest 在后台线程加载图像、纹理、字体、音频,通过回调通知完成,避免主线程卡顿。
大资源(高清图、大音频)同步加载会阻塞主线程导致卡顿。
XGE 提供异步加载框架:
• 发起请求 → 后台线程执行 I/O + 解码
• 主线程每帧 Poll 或等待回调
• 支持取消、线程开关
可异步加载:Image、Texture、Font、Sound。
| 函数 | 说明 |
|---|---|
void xgeAsyncRequestInit(xge_async_request pRequest) | 初始化请求对象 |
void xgeAsyncRequestFree(xge_async_request pRequest) | 释放请求对象 |
int xgeAsyncRequestCancel(xge_async_request pRequest) | 取消进行中的请求 |
int xgeAsyncThreadingSet(int bEnabled) | 启用/禁用多线程 |
int xgeAsyncThreadingGet(void) | 查询多线程状态 |
int xgeAsyncPoll(xge_async_request pRequest) | 轮询完成状态 |
int xgeAsyncImageLoad(xge_async_request pRequest, xge_image pImage, const char* sPath, uint32_t iFlags, xge_async_proc onComplete, void* pUser) | 异步加载图像 |
int xgeAsyncTextureLoad(xge_async_request pRequest, xge_texture pTexture, const char* sPath, uint32_t iFlags, xge_async_proc onComplete, void* pUser) | 异步加载纹理 |
int xgeAsyncFontLoad(xge_async_request pRequest, xge_font pFont, const char* sPath, float fSize, xge_async_proc onComplete, void* pUser) | 异步加载字体 |
int xgeAsyncSoundLoad(xge_async_request pRequest, xge_sound pSound, const char* sPath, xge_async_proc onComplete, void* pUser) | 异步加载音效 |
gcc -O2 -I. -o ch114.exe ch114_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch114.exe
// 回调函数:加载完成后在主线程调用
void onTextureReady(int iResult, void* pUser) {
if (iResult == 0) {
xgeLogWrite(XGE_LOG_INFO,
"纹理加载完成");
} else {
xgeLogWrite(XGE_LOG_ERROR,
"纹理加载失败: %d", iResult);
}
}
// 启用多线程加载
xgeAsyncThreadingSet(1);
// 发起异步纹理加载
xge_async_request_t req;
xgeAsyncRequestInit(&req);
xge_texture_t texBg;
xgeAsyncTextureLoad(&req, &texBg,
"textures/background_4k.png",
0, onTextureReady, NULL);
// 方式 A:回调自动通知(推荐)
// 方式 B:手动轮询
void onFrame(void) {
if (xgeAsyncPoll(&req)) {
// 已完成,可以使用 texBg
xgeDraw(&texBg, 0, 0);
} else {
// 显示加载指示器
drawLoadingSpinner();
}
}
// 取消(如切换场景)
xgeAsyncRequestCancel(&req);
// 释放
xgeAsyncRequestFree(&req);将以下代码保存为 ch114_main.c,编译后运行即可看到异步加载纹理效果:
#include "xge.h"
#include <math.h>
static xge_async_request_t g_req;
static xge_texture_t g_tex;
static xge_font g_font = NULL;
static int g_loaded = 0;
static float g_time = 0.0f;
static void onTexReady(int iResult, void* pUser) {
(void)pUser;
if (iResult == 0) {
g_loaded = 1;
xgeLogWrite(XGE_LOG_INFO, "Texture loaded!");
} else {
xgeLogWrite(XGE_LOG_ERROR, "Load failed: %d", iResult);
}
}
static int onFrame(void* pUser) {
(void)pUser;
g_time += 0.016f;
xgeClear(0x081114FF);
if (g_loaded) {
// 加载完成,绘制纹理
xgeDraw(&g_tex, 200, 150);
xgeTextDraw(g_font, "Texture loaded!",
50, 50, 0x4FD8C2FF);
} else {
// 加载中:显示旋转动画
float cx = 400, cy = 300;
for (int i = 0; i < 8; i++) {
float a = g_time * 4.0f + i * 0.785f;
float r = 30.0f;
uint32_t c = (i == 0) ? 0xFFFFFFFF : 0x555555FF;
xgeShapeCircleFill(
cx + r*cosf(a), cy + r*sinf(a), 5, c);
}
xgeTextDraw(g_font, "Loading...",
350, 350, 0xFFFFFFFF);
}
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 800;
d.iHeight = 600;
d.sTitle = "ch114 - Async Load";
d.iFlags = XGE_INIT_VSYNC;
xgeInit(&d);
// 启用多线程加载
xgeAsyncThreadingSet(1);
xgeAsyncRequestInit(&g_req);
// 发起异步纹理加载
xgeAsyncTextureLoad(&g_req, &g_tex,
"textures/background.png",
0, onTexReady, NULL);
g_font = xgeFontLoad("res/font/default.ttf", 24);
xgeRun(onFrame, NULL);
xgeAsyncRequestFree(&g_req);
xgeFontFree(g_font);
xgeUnit();
return 0;
}权威源码为 examples/tutorial_capture/ch114_main1.c。为保证 CI/截图结果确定,它关闭异步线程并调用 xgeAsyncSoundLoad、xgeAsyncPoll,断言请求进入 XGE_ASYNC_READY 后播放声音。生产环境可开启线程,但必须在主线程持续轮询并处理失败与取消。
