BCB临界区的使用

       使用BCB陆续十多年了,因为一直在工控领域主要是做串口和网络通信类的小软件,BCB6.0足够用,对C++应用得并不是很深。
       在读写外部设备时也会用多线程(为了避免主程序在操控过程中的卡顿),如串口和数据库,最主要还是操作数据库,开几个线程来分开独立读写数据库还是挺自在的。
但因为自己的项目中几乎没有出现同时写一个表的情况,所以都是在主程序中控制多线程的写入数据库时机,多少年来一直这么干也没出过事。

       新到一个工控公司,出于成本的考虑需要用一些轻量型的数据库,于是就不得不改换用新的数据库,这个数据库没有了并发机制,读写不能同时执行。这下惯用的多线程程序接二连三地崩溃,因此不得不认真研究多线程的同步问题,用用心,很快就改好了,按照自己的方案新改一个小程序备案。
       网上绝大多数C++多线程案例都是正确的废话,理论性的,顶多用个控制台来演示下自加自减效果,对于菜鸟级的是没法移植,我就从实用性的角度写一个简单理解和便于移植的BCB6.0的多线程以供入门者参考。

       简单说明下多线程的原理,不复制理论了,自己的理解:因为电脑的CPU执行速度很快,一般它90%以上的时间都是空闲的,软件执行正常的内存操作都是很快的,而读写外部设备是较慢的,很花时间(相对读写内存)。如果用单线程就会出现程序卡顿的现象,如果非必须的情况:如程序中的每一步环环相扣,上一步的结果是下一步的执行输入条件,那也没法用多线程。
       本多线程是使用的临界区——CRITICAL_SECTION
       模拟状态是这样的:
       线程正在写一个文件时主程序通知该线程再写入一条数据,在两次写文件都还没完成时主线程又要通知该线程执行读文件。
在此不考虑优先级问题,只要按照线程通知的顺序执行就行了。
       程序的执行原理是这样的,一个多线程里面包含了读和写test.txt记事本的功能。

       因为读写记事本的消耗时间很短,在写记事本里面故意加了2s延时以造成多线程的明显冲突。


       按下按钮,通知线程要写入一串字符(线程执行完需要2s以上),延时20ms后通知线程再写入一串字符,跟第一次写入造成“冲突”,延时20ms后,在两个写都没完成时再通知线程要读同一个记事本。 因此故意制造了线程中三个事件“打架”
       可通过临界区成功解决了线程执行的冲突问题,最终3个事件都会完美执行。可以很轻易地改成对数据库的操作,若使用ADO需要在线程中对COM对象初始化(CoInitialize)。
       本例是解决同一个多线程的同时执行冲突问题,同理也可以用全局变量临界区来协调多个不同线程的同步问题。

在大当量的任务中用这个方案是有弊端的,非本文考虑范围。

       核心代码:

void __fastcall Wrtext::Execute()
{
    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0)) //一直等主线程消息通知
    {
        try
        {
            Lock();   //进入临界区  如果还没出临界区又有新消息进来,不用担心,它们会排队等待的
            try
            {
                switch(msg.message)
                {
                case WRITE_DATA :   //写记录
                    WriteData(msg.wParam, msg.lParam);
                    Sleep(2000);//故意延时仿真执行事件的时间长 //
                    break;

                case READ_DATA :    //读记录
                    Synchronize(ReadData);
                    break;

                default
                        :
                    break;
                }
            }
            catch(Exception &e)
            {
                //LOG(e); //LOG是日志记录类
            }
            catch(...)
            {
                //LOG("未知异常!"); 
            }
        }
        __finally
        {
            Unlock();  //退出临界区 让排队的可以进来了
        }
    }
}

下载:BCB临界区多线程 

对于新手可以学习以下几个知识点:

1、多线程临界区同步
2、多线程消息机制
3、读写记事本
4、线程与VCL控件同步

5、控件自适应窗体大小变化(鼠标拉动界面边界改变大小看看效果)


猜你喜欢

转载自blog.csdn.net/gongzhu110/article/details/79512035