这Apolwin nt鼠标不能用多少钱

如果是做底层嵌入式开发的人,对于函数的可重入性在多任务系统下的理解应该是比较深刻的,如果不理解清楚任务是如何调度的,任务之间的通讯机制是怎样的,那之后的系统设计就无从下手。如果是经常做上层开发的人,可能不需要去搞清楚界面的主函数里到底干了什么,也不需要搞懂开始多线程之后对函数本身的可重入性有什么要求。所以我在着手写了上一篇博客《》之后,第一件事情就是设计一个涉及到多任务(多线程)的界面,从中分析GTK的消息循环和任务调度机制。

还不清楚GTK和Glade的使用的人可以参考我的上一篇博客,这里不再累述。

多线程在界面设计里是非常重要的,比如,可以新开一个线程单独进行逻辑处理、IO读取,主线程用于界面显示,这样就不会出现因为逻辑处理时所堵塞导致界面死掉。但是,一旦开始多线程,最需要关心的一点就是数据的保护。一般情况下,不允许多个线程在同一时刻对同一个资源进行读写(比如一个全局变量,一个界面标签上的text),否则会照成无法预计的冲突,特别是在界面更新这一点上。若使用windows的.Net进行开发的话可以使用BeginInvoke方法实现进行异步调度,其中封装了类似于互斥信号量的机制来保护共享控件(这里是界面)。windows下直接不允许其他线程修改界面更新线程,即主线程。但是gtk下是可以的,因为,它不会添加线程保护代码。这样就导致安全性下降,而且实际上在别的线程进行界面修改确实会产生很多问题,所以我们得自己添加代码进行保护,这就涉及到多线程之间的调度问题。

考虑下面一个问题:设计一个界面包含三个按钮和一个label,点击一个按钮可以递增label上的数,点击另一个可以清零,点击最后一个可以自动开启一个计时器进行递增,将递增的结果显示在界面上,并且递增的速度能在程序中修改。前两个按钮很好设计,最后一个按钮我们采用新建一个线程的方法进行处理。所有源代码在最后都有打包下载。

【方法一:粗暴的多线程保护】

首先需要说明的是,gtk中不支持线程的直接挂起(suspend)和恢复(resume),也不支持在程序中直接销毁一个线程。若使用线程池的话或许能从侧面解决这一问题,这有待验证。在的人来说,像这种定时器的问题简单的几行代码就好了,但是鉴于gtk还是一种比较纯净的C代码来实现的,所以很多工作需要我们自己添加。

如图所示,点击第三个按钮时,将会新建一个GSource,timeoutSrc用于连接一个更新label的函数,并插入到主循环中每次主循环扫描时执行。新建一个GTimer类型的ticker,用于技术。由于gtk中没有一个很好的定时中断机制让定时器自动产生中断,所以还是得我们自己编写代码查询。(其实只要查询速度够快,跟中断机制的效果差不多的)。对于定时器ticker的查询我为了区别前面的线程操作,故意在主循环中,而且是Idle空闲任务中插入查询函数IdleTickerScan进行定时器的查询,若到达一定的定时时间,将利用消息对列发送一则消息g_async_queue_push();与此同时TimerThread一开始被建立,但是一直卡在g_async_queue_pop()处,没有消息是无法继续进行的。一旦IdleTickerScan中发送一则消息,TimerThread将会收到消息,并清空这则消息,往下执行直到下个循环继续等待。

注意到这里,IdleTickerScan是加载主循环的Idle任务中的。一般每次主循环中的Idle任务都是一个空循环,而且循环次数不止一次,所以IdleTickerScan每次主循环将不止执行一次,而且这里不能放太多的代码降低系统效率。有人将多线程中更新主界面的功能放在Idle里,其实这样是没有必要的,而且将有可能导致空闲任务反而任务繁重。更新界面可以就像我这样新建一个插在主循环中每隔30ms更新一次就可以了。

整个系统设计下来感觉比较复杂,主要是自己需要些的代码比较多,这也正是C代码的一大特点,代码可能比较多,但是经过自己精心维护却能对每一步的道理都能了解清楚。

以上三种方法所有代码,以及编译脚本的下载:

注意,编译时假设你的gtk目录在c:\gtk\,gcc(MinGW)在C:\MinGW\。若不是,请自行修改编译和运行脚本的路径。

若不清楚gtk是怎么安装的,参考我的博客《》进行安装。

我要回帖

更多关于 win nt鼠标不能用 的文章

 

随机推荐