zoukankan      html  css  js  c++  java
  • 同步异步和阻塞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,这反而不如同步阻塞模式了。

  • 相关阅读:
    Excel 相关实用计算公式
    C# ThreadState属性分析
    U8 数据库服务器和应用服务器 分离后出现 登陆系统管理 远程组件初始化 失败 解决方案!
    MyEclipse 快捷键
    项目中用到的开源框架
    spring.net nhibernate 不一定是自增变量,也可能是触发器 Batch update returned unexpected row count from update; actual row count: 2; expected: 1
    解决方法: A C3P0Registry mbean is already registered.This probably means that an application using c3p0的警告信息处理
    NHibenate hbm.xml 自动 生成 数据库表的时候 长度为1
    解决方法: Failed to load the sqljdbc_auth.dll
    SQL 中判断 纯数字
  • 原文地址:https://www.cnblogs.com/organic/p/7784047.html
Copyright © 2011-2022 走看看