⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap12_3.htm

📁 MFC开发基础教程
💻 HTM
📖 第 1 页 / 共 3 页
字号:
      </font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">} 
      COMMTIMEOUTS,*LPCOMMTIMEOUTS;</p>
    </blockquote>
    <p ALIGN="JUSTIFY">COMMTIMEOUTS</font><font SIZE="3">结构的成员都以毫秒为单位。总超时的计算公式是:</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">总超时</font><font FACE="Times New Roman" SIZE="3">=</font><font SIZE="3">时间系数×要求读</font><font FACE="Times New Roman" SIZE="3">/</font><font SIZE="3">写的字符数 </font><font FACE="Times New Roman" SIZE="3">+ </font><font SIZE="3">时间常量</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">例如,如果要读入</font><font FACE="Times New Roman" SIZE="3">10</font><font SIZE="3">个字符,那么读操作的总超时的计算公式为:</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">读总超时=</font><font FACE="Times New Roman" SIZE="3">ReadTotalTimeoutMultiplier</font><font SIZE="3">×</font><font FACE="Times New Roman" SIZE="3">10 + ReadTotalTimeoutConstant</p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">可以看出,间隔超时和总超时的设置是不相关的,这可以方便通信程序灵活地设置各种超时。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">如果所有写超时参数均为</font><font FACE="Times New Roman" SIZE="3">0</font><font SIZE="3">,那么就不使用写超时。如果</font><font FACE="Times New Roman" SIZE="3">ReadIntervalTimeout</font><font SIZE="3">为</font><font FACE="Times New Roman" SIZE="3">0</font><font SIZE="3">,那么就不使用读间隔超时,如果</font><font FACE="Times New Roman" SIZE="3">ReadTotalTimeoutMultiplier</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">ReadTotalTimeoutConstant</font><font SIZE="3">都为</font><font FACE="Times New Roman" SIZE="3">0</font><font SIZE="3">,则不使用读总超时。如果读间隔超时被设置成</font><font FACE="Times New Roman" SIZE="3">MAXDWORD</font><font SIZE="3">并且两个读总超时为</font><font FACE="Times New Roman" SIZE="3">0</font><font SIZE="3">,那么在读一次输入缓冲区中的内容后读操作就立即完成,而不管是否读入了要求的字符。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">在用重叠方式读写串行口时,虽然</font><font FACE="Times New Roman" SIZE="3">ReadFile</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">WriteFile</font><font SIZE="3">在完成操作以前就可能返回,但超时仍然是起作用的。在这种情况下,超时规定的是操作的完成时间,而不是</font><font FACE="Times New Roman" SIZE="3">ReadFile</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">WriteFile</font><font SIZE="3">的返回时间。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">清单</font><font FACE="Times New Roman" SIZE="3">12.5</font><font SIZE="3">列出了一段简单的串行口初始化代码。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><b><font SIZE="3"> </p>
    <p ALIGN="JUSTIFY">清单</font><font FACE="Times New Roman" SIZE="3">12.5 </font><font SIZE="3">打开并初始化串行口</font></b><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">HANDLE hCom;</p>
    <p ALIGN="JUSTIFY">DWORD dwError;</p>
    <p ALIGN="JUSTIFY">DCB dcb;</p>
    <p ALIGN="JUSTIFY">COMMTIMEOUTS TimeOuts;</p>
    <p ALIGN="JUSTIFY">hCom=CreateFile(</font><font SIZE="3">“</font><font FACE="Times New Roman" SIZE="3">COM2</font><font SIZE="3">”</font><font FACE="Times New Roman" SIZE="3">, // </font><font SIZE="3">文件名</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">GENERIC_READ | GENERIC_WRITE, // </font><font SIZE="3">允许读和写 </font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">0, // </font><font SIZE="3">独占方式</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">NULL, </p>
    <p ALIGN="JUSTIFY">OPEN_EXISTING, //</font><font SIZE="3">打开而不是创建</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // </font><font SIZE="3">重叠方式</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">NULL</p>
    <p ALIGN="JUSTIFY">);</p>
    <p ALIGN="JUSTIFY">if(hCom = = INVALID_HANDLE_VALUE)</p>
    <p ALIGN="JUSTIFY">{</p>
    <p ALIGN="JUSTIFY">dwError=GetLastError( );</p>
    <p ALIGN="JUSTIFY"><b>. . .</b> // </font><font SIZE="3">处理错误</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">}</p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">SetupComm( hCom, 1024, 1024 ) //</font><font SIZE="3">缓冲区的大小为</font><font FACE="Times New Roman" SIZE="3">1024</p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">TimeOuts. ReadIntervalTimeout=1000; </p>
    <p ALIGN="JUSTIFY">TimeOuts.ReadTotalTimeoutMultiplier=500; </p>
    <p ALIGN="JUSTIFY">TimeOuts.ReadTotalTimeoutConstant=5000; </p>
    <p ALIGN="JUSTIFY">TimeOuts.WriteTotalTimeoutMultiplier=500; </p>
    <p ALIGN="JUSTIFY">TimeOuts.WriteTotalTimeoutConstant=5000;</p>
    <p ALIGN="JUSTIFY">SetCommTimeouts(hCom, &amp;TimeOuts); // </font><font SIZE="3">设置超时</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">GetCommState(hCom, &amp;dcb);</p>
    <p ALIGN="JUSTIFY">dcb.BaudRate=2400; // </font><font SIZE="3">波特率为</font><font FACE="Times New Roman" SIZE="3">2400</p>
    <p ALIGN="JUSTIFY">dcb.ByteSize=8; // </font><font SIZE="3">每个字符有</font><font FACE="Times New Roman" SIZE="3">8</font><font SIZE="3">位</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">dcb.Parity=NOPARITY; //</font><font SIZE="3">无校验</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">dcb.StopBits=ONESTOPBIT; //</font><font SIZE="3">一个停止位</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">SetCommState(hCom, &amp;dcb);</p>
    <b><p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font></b><font color="#3973DE" FACE="Times New Roman" SIZE="3">12.3.3 
    </font><font SIZE="3" color="#3973DE">重叠</font><font color="#3973DE" FACE="Times New Roman" SIZE="3">I/O</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">在用</font><font FACE="Times New Roman" SIZE="3">ReadFile</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">WriteFile</font><font SIZE="3">读写串行口时,既可以同步执行,也可以重叠(异步)执行。在同步执行时,函数直到操作完成后才返回。这意味着在同步执行时线程会被阻塞,从而导致效率下降。在重叠执行时,即使操作还未完成,调用的函数也会立即返回。费时的</font><font FACE="Times New Roman" SIZE="3">I/O</font><font SIZE="3">操作在后台进行,这样线程就可以干别的事情。例如,线程可以在不同的句柄上同时执行</font><font FACE="Times New Roman" SIZE="3">I/O</font><font SIZE="3">操作,甚至可以在同一句柄上同时进行读写操作。“重叠”一词的含义就在于此。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">ReadFile</font><font SIZE="3">函数只要在串行口输入缓冲区中读入指定数量的字符,就算完成操作。而</font><font FACE="Times New Roman" SIZE="3">WriteFile</font><font SIZE="3">函数不但要把指定数量的字符拷入到输出缓冲中,而且要等这些字符从串行口送出去后才算完成操作。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">ReadFile</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">WriteFile</font><font SIZE="3">函数是否为执行重叠操作是由</font><font FACE="Times New Roman" SIZE="3">CreateFile</font><font SIZE="3">函数决定的。如果在调用</font><font FACE="Times New Roman" SIZE="3">CreateFile</font><font SIZE="3">创建句柄时指定了</font><font FACE="Times New Roman" SIZE="3">FILE_FLAG_OVERLAPPED</font><font SIZE="3">标志,那么调用</font><font FACE="Times New Roman" SIZE="3">ReadFile</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">WriteFile</font><font SIZE="3">对该句柄进行的读写操作就是重叠的,如果未指定重叠标志,则读写操作是同步的。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">函数</font><font FACE="Times New Roman" SIZE="3">ReadFile</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">WriteFile</font><font SIZE="3">的参数和返回值很相似。这里仅列出</font><font FACE="Times New Roman" SIZE="3">ReadFile</font><font SIZE="3">函数的声明:</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">BOOL ReadFile(</p>
    <blockquote>
      <p ALIGN="JUSTIFY">HANDLE hFile, // </font><font SIZE="3">文件句柄</p>
      </font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">LPVOID lpBuffer, // </font><font SIZE="3">读缓冲区</p>
      </font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">DWORD 
      nNumberOfBytesToRead, // </font><font SIZE="3">要求读入的字节数 </font><font FACE="Times New Roman" SIZE="3"></p>
      <p ALIGN="JUSTIFY">LPDWORD lpNumberOfBytesRead, // </font><font SIZE="3">实际读入的字节数</p>
      </font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">LPOVERLAPPED lpOverlapped 
      // </font><font SIZE="3">指向一个</font><font FACE="Times New Roman" SIZE="3">OVERLAPPED</font><font SIZE="3">结构</p>
      </font><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">); //</font><font SIZE="3">若返回</font><font FACE="Times New Roman" SIZE="3">TRUE</font><font SIZE="3">则表明操作成功</font></p>
    </blockquote>
    <p><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">需要注意的是如果该函数因为超时而返回,那么返回值是</font><font FACE="Times New Roman" SIZE="3">TRUE</font><font SIZE="3">。参数</font><font FACE="Times New Roman" SIZE="3">lpOverlapped</font><font SIZE="3">在重叠操作时应该指向一个</font><font FACE="Times New Roman" SIZE="3">OVERLAPPED</font><font SIZE="3">结构,如果该参数为</font><font FACE="Times New Roman" SIZE="3">NULL</font><font SIZE="3">,那么函数将进行同步操作,而不管句柄是否是由</font><font FACE="Times New Roman" SIZE="3">FILE_FLAG_OVERLAPPED</font><font SIZE="3">标志建立的。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">当</font><font FACE="Times New Roman" SIZE="3">ReadFile</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">WriteFile</font><font SIZE="3">返回</font><font FACE="Times New Roman" SIZE="3">FALSE</font><font SIZE="3">时,不一定就是操作失败,线程应该调用</font><font FACE="Times New Roman" SIZE="3">GetLastError</font><font SIZE="3">函数分析返回的结果。例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回</font><font FACE="Times New Roman" SIZE="3">FALSE</font><font SIZE="3">,而且</font><font FACE="Times New Roman" SIZE="3">GetLastError</font><font SIZE="3">函数返回</font><font FACE="Times New Roman" SIZE="3">ERROR_IO_PENDING</font><font SIZE="3">。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">在使用重叠</font><font FACE="Times New Roman" SIZE="3">I/O</font><font SIZE="3">时,线程需要创建</font><font FACE="Times New Roman" SIZE="3">OVERLAPPED</font><font SIZE="3">结构以供读写函数使用。</font><font FACE="Times New Roman" SIZE="3">OVERLAPPED</font><font SIZE="3">结构最重要的成员是</font><font FACE="Times New Roman" SIZE="3">hEvent</font><font SIZE="3">,</font><font FACE="Times New Roman" SIZE="3">hEvent</font><font SIZE="3">是一个事件对象句柄,线程应该用</font><font FACE="Times New Roman" SIZE="3">CreateEvent</font><font SIZE="3">函数为</font><font FACE="Times New Roman" SIZE="3">hEvent</font><font SIZE="3">成员创建一个手工重置事件,</font><font FACE="Times New Roman" SIZE="3">hEvent</font><font SIZE="3">成员将作为线程的同步对象使用。如果读写函数未完成操作就返回,就那么把</font><font FACE="Times New Roman" SIZE="3">hEvent</font><font SIZE="3">成员设置成无信号的。操作完成后(包括超时),</font><font FACE="Times New Roman" SIZE="3">hEvent</font><font SIZE="3">会变成有信号的。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">如果</font><font FACE="Times New Roman" SIZE="3">GetLastError</font><font SIZE="3">函数返回</font><font FACE="Times New Roman" SIZE="3">ERROR_IO_PENDING</font><font SIZE="3">,则说明重叠操作还为完成,线程可以等待操作完成。有两种等待办法:一种办法是用象</font><font FACE="Times New Roman" SIZE="3">WaitForSingleObject</font><font SIZE="3">这样的等待函数来等待</font><font FACE="Times New Roman" SIZE="3">OVERLAPPED</font><font SIZE="3">结构的</font><font FACE="Times New Roman" SIZE="3">hEvent</font><font SIZE="3">成员,可以规定等待的时间,在等待函数返回后,调用</font><font FACE="Times New Roman" SIZE="3">GetOverlappedResult</font><font SIZE="3">。另一种办法是调用</font><font FACE="Times New Roman" SIZE="3">GetOverlappedResult</font><font SIZE="3">函数等待,如果指定该函数的</font><font FACE="Times New Roman" SIZE="3">bWait</font><font SIZE="3">参数为</font><font FACE="Times New Roman" SIZE="3">TRUE</font><font SIZE="3">,那么该函数将等待</font><font FACE="Times New Roman" SIZE="3">OVERLAPPED</font><font SIZE="3">结构的</font><font FACE="Times New Roman" SIZE="3">hEvent </font><font SIZE="3">事件。</font><font FACE="Times New Roman" SIZE="3">GetOverlappedResult</font><font SIZE="3">可以返回一个</font><font FACE="Times New Roman" SIZE="3">OVERLAPPED</font><font SIZE="3">结构来报告包括实际传输字节在内的重叠操作结果。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">如果规定了读</font><font FACE="Times New Roman" SIZE="3">/</font><font SIZE="3">写操作的超时,那么当超过规定时间后,</font><font FACE="Times New Roman" SIZE="3">hEvent</font><font SIZE="3">成员会变成有信号的。因此,在超时发生后,</font><font FACE="Times New Roman" SIZE="3">WaitForSingleObject</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">GetOverlappedResult</font><font SIZE="3">都会结束等待。</font><font FACE="Times New Roman" SIZE="3">WaitForSingleObject</font><font SIZE="3">的</font><font FACE="Times New Roman" SIZE="3">dwMilliseconds</font><font SIZE="3">参数会规定一个等待超时,该函数实际等待的时间是两个超时的最小值。注意</font><font FACE="Times New Roman" SIZE="3">GetOverlappedResult</font><font SIZE="3">不能设置等待的时限,因此如果</font><font FACE="Times New Roman" SIZE="3">hEvent</font><font SIZE="3">成员无信号,则该函数将一直等待下去。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">在调用</font><font FACE="Times New Roman" SIZE="3">ReadFile</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">WriteFile</font><font SIZE="3">之前,线程应该调用</font><font FACE="Times New Roman" SIZE="3">ClearCommError</font><font SIZE="3">函数清除错误标志。该函数负责报告指定的错误和设备的当前状态。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">调用</font><font FACE="Times New Roman" SIZE="3">PurgeComm</font><font SIZE="3">函数可以终止正在进行的读写操作,该函数还会清除输入或输出缓冲区中的内容。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><b><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font></b><font color="#3973DE" FACE="Times New Roman" SIZE="3">12.3.4 
    </font><font SIZE="3" color="#3973DE">通信事件</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">在</font><font FACE="Times New Roman" SIZE="3">Windows 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -