Mint_21.3 drawing-area和goocanvas的FB笔记(三)

一、改变goocanvas线条自动画线时间间隔

通过系统SIGALRM信号触发,每秒画一条线对于慢温湿度等慢变信号可以应付,但对于快速信号1秒的间隔就太慢了。可以改变方式,通过另外的线程,完成要做的任务。

1. 线程的回调函数 myfunc

2. 循环运行的线程函数 threadtimer

3. 创建线程,无需等待线程结束

4. 进入主程循环

#include once "glib.bi"'Thread callback
Function myfunc Cdecl (Byval NotUsed As Any Ptr) as guintPrint "Main-program time = ", Time$Return TRUE
End Function'Thread endless loop
Function threadtimer(ByVal invalue as Integer) as integerDo while inkey$<> CHR$(27)Sleep 200Print "Thead-process time = ", Time$myfunc(NULL)LoopReturn TRUE
End function'Create thread
Dim as any ptr threadid = threadcreate( CAST(Any Ptr, @threadtimer), 0 )'Main loop
'Press ESC to terminate
Do while inkey$<>chr$(27)Sleep 100
LoopEnd

执行结果:

7e059520ca5749b99fdba50fa189b3a2.png

FreeBasic是多线程的,根据需要还可以创建更多线程,线程循环中sleep 200改为 sleep 100 则线程任务被执行的频率就会更高。

二、让SIGALRM为线程提供安全保护

上面的线程是个死循环,如果主程序很长,任务很重等其它原因死掉了,线程应该自动退出、让出系统资源。让SIGALRM做此事情即可解决这一问题。

系统在正常运行时,SIGALRM应该是长活的,如同C#中的系统线程池,它不是由用户创建的。它可以自动更新共享变量,在线程循环中对变量更新进行判断,如果SIGALRM在更新共享变量,则清FlagSet, 否则自动累加,这样如果因程序死掉了而不能更新共享变量的话,线程应该也就因此自动结束了。

三、可以使用线程锁

如果线程读写变得复杂,可以对变量或过程读写加锁,freebasic 支持 mutexlock 和 mutexunlock。

#include once "glib.bi"const SIGALRM=14
Dim shared as Integer FlagSet = 0
Dim shared as Integer FlagCounterNew = 0
Dim shared as Integer FlagCounterOld = 0Dim shared as any ptr maintlock, threadlock
Dim as any ptr threadidDeclare Function Signal cdecl  alias "signal" (ByVal V_Signal As long, byval V_Function As Any Ptr) as Any Ptr
Declare Function Raise cdecl  alias "raise" (ByVal V_Signal As long) as Any Ptr
Declare function alarm cdecl alias "alarm" (byval __seconds as uinteger) as uintegermainlock = mutexcreate( )
threadlock = mutexcreate( )'Thread callback
Function myfunc Cdecl (Byval NotUsed As Any Ptr) as guintPrint "Main-program time = ", Time$Return TRUE
End Function'Thread endless loop
Function threadtimer(ByVal invalue as Integer) as integerDo while inkey$<> CHR$(27)Mutexlock threadlockIf FlagCounterNew <> FlagCounterOld thenFlagSet = 0FlagCounterOld = FlagCounterNewElseFlagSet += 1If FlagSet > 20 thenFlagSet = 0Exit DoEnd ifEnd ifMutexUnlock threadlockSleep 200Print "Thead-process time = ", Time$myfunc(NULL)LoopReturn TRUE
End functionSub timerevent()MutexLock mainlockFlagCounterNew += 1If FlagCounterNew > 1000 thenFlagCounterNew = 0End ifMutexUnlock mainlock
End Subsub wait_alarm(iSigno As Integer)'?"This is the scheduled event SIG = " & Str$(iSigno) & "--- @: " & Time$alarm(1)		'loads another alarm events: each alarm event is a single time event, so to repeat it it must be set again every timetimerevent
end subsignal(SIGALRM, @wait_alarm)		'when SIGALRM triggered, call subroutine wait_alarm
alarm(2)	'Create thread
threadid = threadcreate( CAST(Any Ptr, @threadtimer), 0 )'Main loop
'Press ESC to terminate
Do while inkey$<>chr$(27)Sleep 100
LoopEnd

如果是gtk界面程序,可以简单地使用g_timeout_add(100, @myfunc, NULL) 完成100毫秒间隔的回调函数执行,直到回调函数返回FALSE结束。

#INCLUDE once gtk/gtk.h
#DEFINE __USE_GTK3__

'Thread callback
Function myfunc Cdecl (Byval NotUsed As Any Ptr) as guint
     Print "Callback time = ", Time$
    Return TRUE
End Function

gtk_init(NULL, NULL)
g_timeout_add(100, @myfunc, NULL)
gtk_main()

如果还有一个回调任务要完成,则加多一行任务,比如:

g_timeout_add(100, @myfunc1, NULL)

g_timeout_add(100, @myfunc2, NULL)

可直接编译运行的实测代码:

#DEFINE __USE_GTK3__
#Include once "gtk/gtk.bi"Declare Function myfunc Cdecl (Byval NotUsed As Any Ptr) as guint'Thread callback
Function myfunc Cdecl (Byval NotUsed As Any Ptr) as guintPrint "Callback time = ", Time$Return TRUE
End Functiongtk_init(NULL, NULL)
var mycall = g_timeout_add (100, @myfunc, NULL)
gtk_main()

上面的代码测试了Timer, 但主程序只能等待gtk_main()结束才能继续。如果将gtk这段代码作为一个线程运行,而且主程序不等待线程结束的话,则线程运行的同时主程序仍然继续运行。

测试代代码改写为:

#DEFINE __USE_GTK3__
#Include once "gtk/gtk.bi"Declare Function myfunc Cdecl (Byval NotUsed As Any Ptr) as guint'Thread callback
Function myfunc Cdecl (Byval NotUsed As Any Ptr) as guintPrint "Callback time = ", Time$Return TRUE
End FunctionSub sidethread()gtk_init(NULL, NULL)var mycall = g_timeout_add (300, @myfunc, NULL)gtk_main()
End SubDim as any ptr threadid = threadcreate( CAST(Any Ptr, @sidethread), 0 )''Main loop
Do while inkey$<>chr$(27)Print "Main program time = ", Time$Sleep 100
LoopEnd 0

Gnu 对 glib 描述有一段文字(): Libraries may contain wrappers of some of these functions, e.g. gtk_main(), gtk_main_quit() and gtk_events_pending().

是说gtk_main(), gtk_main_quit,gtk_events_pending() 是 g_main_xxx 的封装 (wrapper) --- (Gnu 站点链接贴图本意只是为了不在CSDN外链)。上面的测试程序引用了 gtk,下面的测试程序使用glib验证了同样的效果。

#Include once "glib.bi"Declare Function myfunc Cdecl (Byval NotUsed As Any Ptr) as guint'Thread callback
Function myfunc Cdecl (Byval NotUsed As Any Ptr) as guintPrint "Callback time = ", Time$Return TRUE
End FunctionDim shared as GMainLoop PTR gml = NULL
Sub sidethread()gml = g_main_loop_new(NULL, FALSE)var mycall = g_timeout_add (300, @myfunc, NULL)g_main_loop_run(gml)g_main_loop_unref(gml)
End SubDim as any ptr threadid = threadcreate( CAST(Any Ptr, @sidethread), 0 )''Main loop
Do while inkey$<>chr$(27)Print "Main program time = ", Time$Sleep 100
Loop'When main program terminate, all thread should be removed off
'but, anyway, g_main_loop_quit(gml) is not harm to added here
g_main_loop_quit(gml)
End 0

在CSDN上又查看了些关于Glib的博客,补了一句:g_main_loop_unref(gml)

学习参考博主李尔阳博文:七、GLib主要的事件循环(The Main Event Loop)_glib 事件源 套接字-CSDN博客

凭籍多线程能力,可以在主程序中实现对其它语言封装的.so界面进行调用。gcc的.so封装和freebasic的.so封装需要一些方法,但试练都不是特别复杂。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/509489.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java架构之路-架构应全面了解的技术栈和工作域

有时候我在想这么简单简单的东西&#xff0c;怎么那么难以贯通。比如作为一个架构师可能涉及的不单单是技术架构&#xff0c;还包含了项目管理&#xff0c;一套完整的技术架构也就那么几个技术栈&#xff0c;只要花点心思&#xff0c;不断的往里面憨实&#xff0c;总会学的会&a…

太阳能风吸式杀虫灯是什么

TH-FD1随着农业科技的不断进步&#xff0c;太阳能风吸式杀虫灯作为一种新兴的绿色农业技术&#xff0c;正逐渐走进人们的视野。这种集太阳能和风吸技术于一体的杀虫设备&#xff0c;不仅具有环保节能的特点&#xff0c;还能有效减少农药使用&#xff0c;提高农产品质量&#xf…

KBP310-ASEMI小功率电源适配器KBP310

编辑&#xff1a;ll KBP310-ASEMI小功率电源适配器KBP310 型号&#xff1a;KBP310 品牌&#xff1a;ASEMI 封装&#xff1a;KBP-4 正向电流&#xff08;Id&#xff09;&#xff1a;3A 反向耐压&#xff08;VRRM&#xff09;&#xff1a;1000V 正向浪涌电流&#xff1a;6…

帮公司面试了个要25K的测试,我问了他这些问题...

深耕IT行业多年&#xff0c;我们发现&#xff0c;对于一个程序员而言&#xff0c;能去到一线互联网公司&#xff0c;会给我们以后的发展带来多大的影响。 很多人想说&#xff0c;这个我也知道&#xff0c;但是进大厂实在是太难了&#xff0c;简历投出去基本石沉大海&#xff0…

【扩散模型】生成模型中的Residual Self-Attention UNet 以及 DDPM的pytorch代码

参考&#xff1a; [1] https://github.com/xiaohu2015/nngen/blob/main/models/diffusion_models/ddpm_cifar10.ipynb [2] https://www.bilibili.com/video/BV1we4y1H7gG/?spm_id_from333.337.search-card.all.click&vd_source9e9b4b6471a6e98c3e756ce7f41eb134 TOC 1 UNe…

正信法律:借款纠纷的民事起诉状怎么写

在借款纠纷中&#xff0c;当协商无果时&#xff0c;诉诸法律成为债权人追回债务的有效途径。而民事起诉状作为启动诉讼程序的法律文书&#xff0c;其撰写质量直接关系到案件的受理与判决。本文旨在简明扼要地阐述如何撰写一份规范的借款纠纷民事起诉状。 起诉状需包含以下几个关…

Ruoyi框架上传文件

axios资料&#xff1a;axios中文文档|axios中文网 | axios axiosjson 默认情况下&#xff0c;axios将JavaScript对象序列化为JSON。 submit(data) {if (data && this.definitionId) {// 启动流程并将表单数据加入流程变量startProcess(this.definitionId, JSON.string…

Ubuntu安装MySQL、Redis、Ningx、jdk等常用环境

Ubuntu安装MySQL、Redis、Ningx、jdk等常用环境 背景&#xff1a;每次安装都要打开好几个文章&#xff0c;此处一篇文章足以 文章目录 Ubuntu安装MySQL、Redis、Ningx、jdk等常用环境一、Ubuntu安装 jdk8①&#xff1a;更新软件包列表②&#xff1a;安装OpenJDK 8③&#xff1a…

神经网络结构——CNN、RNN、LSTM、Transformer !!

文章目录 前言 一、什么是CNN 网络结构 解决问题 工作原理 实际应用 二、什么是RNN 网络结构 解决问题 工作原理 应用场景 三、什么是LSTM 网络结构 解决问题 工作原理 应用场景 四、什么是Transformer 网络结构 解决问题 工作原理 BERT GPT 前言 本文将从什么是CNN&#xff1…

0.考试介绍

上午题较简单&#xff1b; 下午题较难&#xff0c;大部分人不过是因为下午题没过&#xff1b; 考试面广&#xff0c;但不深&#xff1b; 1.1.2删除了原码、反码、补码相关知识&#xff1b; 5.3删除了OSI七层参考模型&#xff1b; 新增的内容&#xff0c;只是作为了解&#x…

Deep Learning相关概念介绍

工具&#xff1a; Anaconda: anaconda.com/products/individual。我理解是一个基于Python的AI程序开发环境&#xff0c;其作用类似于google notebook。区别是google notebook是在网页上&#xff0c;而Anaconda一般是安装在自己的服务器上。Jupyter Notebooks Anaconda激活深度…

Bililive-go 实现直播自动监控录制

前言 最近有直播录制的需求&#xff0c;但是自己手动录制太麻烦繁琐&#xff0c;于是用了开源项目Bililive-go进行全自动监控录制&#xff0c;目前这个项目已经有3K stars了 部署 为了方便我使用了docker compose 部署 version: 3.8 services:bililive:image: chigusa/bilil…