在多线程并发使用的时候,总是在运行过程中莫名其妙的 crash,后面才意识到 LVGL 本身不支持并发,加了互斥锁解决了。

在引入矢量字库时(freetype),又有启动时会概率性 crash 的问题,每次 crash 的地方还不一样,这个坑爬了好久,甚至都怀疑是不是 freetype 有问题,还好总算找到方法解决了,不过还不清楚具体原因,先记录。

以下以 linux 平台下 C++ 语言的方式举例说明,理解方法即可。

一、多线程并发使用

多线程并发使用时,需要在以下两种情况加上互斥锁:

1. 移植时在调用 lv_tick_inc(1) 和 lv_task_handler() 时上锁

// 线程函数
void LvglDrive::prvLvTickTask(LvglDrive *context)
{
while(context->th_tasktick_runing)
{
context->m_lvmutex.lock();
lv_tick_inc(1);
context->m_lvmutex.unlock();
usleep(1 * 1000);
}
return ;
} // 线程函数
void LvglDrive::prvLvHandlerTask(LvglDrive *context)
{
while(context->th_tasktick_runing)
{
context->m_lvmutex.lock();
lv_task_handler();
context->m_lvmutex.unlock();
usleep(5 * 1000);
}
return ;
}

2. 操作控件时上锁

void GuiManager::toast_show(const char *str, unsigned int timeout)
{
LvglDrive::getInstance()->lock();
lv_timer_reset(lv_timer_toast);
lv_timer_pause(lv_timer_toast);
if(timeout){
lv_timer_set_period(lv_timer_toast, timeout);
lv_timer_resume(lv_timer_toast);
}
lv_label_set_text(lv_obj_toast, str);
lv_obj_set_style_pad_top(lv_obj_toast, 5, 0);
lv_obj_set_style_pad_left(lv_obj_toast, 15, 0);
lv_obj_set_style_pad_right(lv_obj_toast, 15, 0);
lv_obj_set_style_pad_bottom(lv_obj_toast, 8, 0);
LvglDrive::getInstance()->unlock();
return ;
} void GuiManager::toast_hide()
{
LvglDrive::getInstance()->lock();
lv_timer_reset(lv_timer_toast);
lv_timer_pause(lv_timer_toast);
lv_label_set_text(lv_obj_toast, "");
lv_obj_set_style_pad_top(lv_obj_toast, 0, 0);
lv_obj_set_style_pad_left(lv_obj_toast, 0, 0);
lv_obj_set_style_pad_right(lv_obj_toast, 0, 0);
lv_obj_set_style_pad_bottom(lv_obj_toast, 0, 0);
LvglDrive::getInstance()->unlock();
return ;
}

二、引入矢量字库(freetype)

需要先把所有需要用到的 UI 控件都创建和初始化完成之后,再去创建两个线程去调用 lv_tick_inc(1) 和 lv_task_handler(),顺序如下:

1、初始化 framebuffer、lv_init()、lv_freetype_init()、lv_port_disp_init()

2、初始化所需要的 UI 控件

3、创建线程调用  lv_task_handler() 、lv_tick_inc(1)

4、按需要设置 UI 控件

bool GuiManager::running()
{
// 初始化 framebuffer、lv_init()、lv_freetype_init()、lv_port_disp_init()
if(LvglDrive::getInstance()->init() == false){
eprintf("lvgl driver running failed!!!\n");
return false;
} ... static lv_ft_info_t ft_info_18;
ft_info_18.name = RES_FONT_PATH;
ft_info_18.weight = 18;
ft_info_18.style = FT_FONT_STYLE_NORMAL | FT_FONT_STYLE_BOLD;
lv_ft_font_init(&ft_info_18); static lv_style_t style_18;
lv_style_init(&style_18);
lv_style_set_text_font(&style_18, ft_info_18.font);
lv_style_set_radius(&style_18, LV_RADIUS_CIRCLE); lv_obj_toast = lv_label_create(lv_layer_sys());
lv_obj_add_style(lv_obj_toast, &style_18, 0);
lv_obj_set_style_bg_opa(lv_obj_toast, LV_OPA_30, 0);
lv_obj_set_style_bg_color(lv_obj_toast, lv_color_black(), 0);
lv_obj_set_style_text_color(lv_obj_toast, lv_color_white(), 0);
lv_label_set_text(lv_obj_toast, "");
lv_obj_set_style_pad_top(lv_obj_toast, 0, 0);
lv_obj_set_style_pad_left(lv_obj_toast, 0, 0);
lv_obj_set_style_pad_right(lv_obj_toast, 0, 0);
lv_obj_set_style_pad_bottom(lv_obj_toast, 0, 0);
lv_obj_align(lv_obj_toast, LV_ALIGN_CENTER, 0, 50); lv_timer_toast = lv_timer_create(on_timer_lv_toast_refresh, 500, this);
lv_timer_pause(lv_timer_toast); ... // 创建线程:prvLvTickTask()、prvLvHandlerTask()
LvglDrive::getInstance()->run();
return true;
}

最新文章

  1. mvc2/3/4_伪静态_路由配置
  2. C#动态调用WCF
  3. js 判断字符串是否包含另外一个字符串
  4. C# 对象 序列化 XML
  5. pycharm 常用设置
  6. PHP自动生成后台导航网址的最佳方法
  7. Linux用户组与用户组进阶命令
  8. Ubuntu 14.10 下NodeJS Cannot find module 'npmlog'
  9. vector容器使用总结 .xml
  10. Debugging Information in Separate Files
  11. 【转】python中的lambda函数
  12. MFC应用程序向导生成的文件
  13. Timer计时不准确的解决方案 每次都重新调整,修正误差
  14. 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
  15. ISP图像质量自动化测试方法
  16. Eclipse debug ‘Source not found’
  17. 如何维持App拥护登录状态(仅仅理论)
  18. win7系统盘扩容后不识别修复方法
  19. 0.python class
  20. Android初级教程调用手机拍照与摄像功能

热门文章

  1. python tcp select 多路复用
  2. java代码整洁之道
  3. android学习 基础知识
  4. 如何通过free看懂内存的真实使用
  5. 记一次node节点无法加入K8S集群
  6. 【云原生 · Kubernetes】Jenkins+Gitlab+Rancher+Docker 实现自动构建镜像的 CI 平台(一)
  7. c++ const和指针
  8. oracle 中模糊查询对like的代替insrt()函数 可以做到效率节约一倍以上
  9. Sqoop的介绍和安装
  10. 函数调用时用const保护指针