• 同步异步和阻塞4-同步非阻塞


    项目简介和code见《同步异步和阻塞2-测试小项目

    1. 实现

    由于IO是阻塞的,所以要实现轮询IO的结果,需要将IO放入线程中处理,IO的处理结果作为给线程的exit code返回。这里用“CBaseThread”简单的将线程处理函数封装到类中

    unsigned CSyncIOByPolling::ThreadWork()
    {
        return IO();
    }

    在OnStart()中,先依次启动2个线程处理IO,然后轮询,一旦有任何一个IO的线程处理完毕后就发送结果

    为了不把CPU占满,这里每次轮询设了一个sleep的时间间隔,然后通过NotifyProgress()函数通知UI当前的进度。

    bool CSyncIOByPolling::OnStart()
    {
        int        nRetArray[] = {-1, -1};
        HANDLE    hThreadArray[] = {NULL, NULL};
    
        int        nThreadNum = sizeof(hThreadArray) / sizeof(hThreadArray[0]);
        for (int i = 0; i < nThreadNum; i++)
        {
            hThreadArray[i] = StartThread();
        }
    
        int        nIndex = 0;
        int        nCompletedNum = 0;
    
        //polling get IO result
        while (true)
        {
            for (int i = 0; i < nThreadNum; i++)
            {
                if (hThreadArray[i])
                {
                    NotifyProgress(nIndex, i);
                    DWORD    dwExitCode = STILL_ACTIVE;
                    if(::GetExitCodeThread(hThreadArray[i], &dwExitCode))
                    {
                        if (STILL_ACTIVE != dwExitCode)
                        {
                            nRetArray[i] = dwExitCode;
                        }
                        else
                        {
                            continue;
                        }
                    }
    
                    ::CloseHandle(hThreadArray[i]);
                    hThreadArray[i] = NULL;
                    NotifyResult(nRetArray[i], i);
                    nCompletedNum++;
                }
            }
    
            if (nCompletedNum >= nThreadNum)
            {
                break;
            }
    
            Sleep(TIMER_ELAPSE);
            nIndex += TIMER_ELAPSE;
        }
    
        return    true;
    }

    简单的从代码长度来看,同步非阻塞模式就明显比同步阻塞模式要复杂。

    2. 测试

    和同步阻塞模式一样,在OnStart()未返回前,”Stop”按钮一直是不可用的,同时UI界面也被卡住(同步模式的老毛病)。

    image

    1> 在同步非阻塞模式下,虽然IO Result还没有结果,却可以看到不断前进的”Progress”(这里由于不知道IO什么时候结束,实际是当前的用掉的时间),这样用户能够知道虽然UI卡住了,但起码程序还是没挂掉的,这就是不阻塞下能多干一些其他有意义的事情带来的好处。

    2> 如果IO没有提供timeout的设置(如本例中的IO()),也可以在轮询中设置一个最大的轮询时间,防止OnStart()一直不返回,导致主线程(很多时候都是UI)不能正常运行。

    3> 轮询模式中使用了多线程,这样实际实现了IO并发,在多个IO处理中,可以缩短所有IO任务处理的总时间

    所以从用户体验上来看,同步非阻塞模式是要优于同步阻塞模式的。

    当然,这里存在一个轮询间隔的问题,一直轮询或轮询间隔小,CPU会大量消耗在无太多意义的轮询code上,如果轮询间隔设得过大,如1s,但如果IO实际完成的时间只有10ms,那么实际IO的完成时间会延长到1s,这反而不如同步阻塞模式了。

  • 相关阅读:
    js 与 jquery 事件对象 比较(转)
    orcle blob转换
    谷歌浏览器和IE下new Date()注意的一个小地方
    让网页在IE下淡入淡出 共17种效果
    SqlHelper的编写
    最授用的数据库连接语句 ado.net
    .NET C#获取当前网页地址信息
    JS设为首页加入收藏代码大全
    CSS进度条
    Convert.ToInt32()与int.Parse()的区别
  • 原文地址:https://www.cnblogs.com/organic/p/7784047.html
Copyright © 2020-2023  润新知