Overlapped结构相关,在线等.(100分)

  • 主题发起人 主题发起人 formality
  • 开始时间 开始时间
F

formality

Unregistered / Unconfirmed
GUEST, unregistred user!
用Overlapped重叠结构时,将操作交给系统去完成。
程序里这样写
WriteFile(m_hComm, lpBuf, dwCount, &dwBytesWritten, &overlapped)
写串口函数返回时,系统帮进程去将内存lpBuf写入m_hComm指向的文件中。如果我这样写系统是否会将lpBuf写完还是只完成一部分,其他的要通过判断dwCount, &dwBytesWritten循环调用WriteFile去写完全部内存lpBuf

也就是说,用Overlapped重叠结构交给系统后台处理时。系统是毫无折扣的完成呢,还是尽它可能去帮进程完成?
需要理由!
 
系统是毫无折扣的完成呢,还是尽它可能去帮进程完成?


这需要你来控制了.

你可以用 GetOverlappedResult 等待它 "毫无折扣的完成"

也可以用 WaitForSingleObject 去让它 "尽它可能完成"
 
我想问Overlapped I/O操作系统是不折扣并不间断的去执行呢?
还是它在闲暇时去执行,一但被别的进程所打断后立即停止并返回?
又或者它如果被别的进程(中断)打断(在执行完其他更高级的请求后)还能返回再继续执行呢?
系统在响应进程的Overlapped I/O请求后是怎么去执行的?
 
请看下面这段代码(著名的SPComm控件内的一段代码):
function TWriteThread.HandleWriteData( lpOverlappedWrite: POverlapped;
pDataToWrite: PChar; dwNumberOfBytesToWrite: DWORD): Boolean;
var
dwLastError,

dwNumberOfBytesWritten,
dwWhereToStartWriting,

dwHandleSignaled: DWORD;
HandlesToWaitFor: array[0..1] of THandle;
begin
Result := False;

dwNumberOfBytesWritten := 0;
dwWhereToStartWriting := 0; // Start at the beginning.

HandlesToWaitFor[0] := hCloseEvent;
HandlesToWaitFor[1] := lpOverlappedWrite^.hEvent;

// Keep looping until all characters have been written.
repeat
// Start the overlapped I/O.
if not WriteFile( hCommFile,
pDataToWrite[ dwWhereToStartWriting ],
dwNumberOfBytesToWrite, dwNumberOfBytesWritten,
lpOverlappedWrite ) then
begin
// WriteFile failed. Expected; lets handle it.
dwLastError := GetLastError;

// Its possible for this error to occur if the
// service provider has closed the port. Time to end.
if dwLastError = ERROR_INVALID_HANDLE then
Exit;

// Unexpected error. No idea what.
if dwLastError <> ERROR_IO_PENDING then
begin
PostHangupCall;
Exit
end;

// This is the expected ERROR_IO_PENDING case.

// Wait for either overlapped I/O completion,
// or for the CloseEvent to get signaled.
dwHandleSignaled := WaitForMultipleObjects(2, @HandlesToWaitFor,
False, INFINITE);

case dwHandleSignaled of
WAIT_OBJECT_0: // CloseEvent signaled!
begin
// Time to exit.
Exit
end;

WAIT_OBJECT_0 + 1: // Wait finished.
begin
// Time to get the results of the WriteFile
if not GetOverlappedResult(hCommFile,
lpOverlappedWrite^,
dwNumberOfBytesWritten, True) then
begin
dwLastError := GetLastError;

// Its possible for this error to occur if the
// service provider has closed the port.
if dwLastError = ERROR_INVALID_HANDLE then
Exit;

// No idea what could cause another error.
PostHangupCall;
Exit
end
end;

WAIT_FAILED: // Wait failed. Shouldn't happen.
begin
PostHangupCall;
Exit
end

else // This case should never occur.
begin
PostHangupCall;
Exit
end
end {case}
end; {WriteFile failure}

// Some data was written. Make sure it all got written.

Dec( dwNumberOfBytesToWrite, dwNumberOfBytesWritten );
Inc( dwWhereToStartWriting, dwNumberOfBytesWritten )
until (dwNumberOfBytesToWrite <= 0); // Write the whole thing!

// Wrote the whole string.
Result := True
end; {TWriteThread.HandleWriteData}


这段代码内只有一个Overlapped结构,基于我的所知道的有关Overlapped知识,
dwHandleSignaled := WaitForMultipleObjects(2, @HandlesToWaitFor,
False, INFINITE);//这里如果等待到lpoverlapp.hEvent信号.则系统肯定已经写完了所有的pDataToWrite指向的内存数据.
那么
GetOverlappedResult(hCommFile,
lpOverlappedWrite^,
dwNumberOfBytesWritten,
True)
这里lpOverlappedWrite 肯定已经等于dwNumberOfBytesToWrite(我认为是肯定的)
因为上面的WaitFor等出的信号说明系统已经(无折扣的)执行完Overlapped请求.
那么它为什么还要判断
Dec( dwNumberOfBytesToWrite, dwNumberOfBytesWritten );
Inc( dwWhereToStartWriting, dwNumberOfBytesWritten );
until (dwNumberOfBytesToWrite <= 0); // Write the whole thing!
再继续循环呢?
 
从这里看
dwHandleSignaled := WaitForMultipleObjects(2, @HandlesToWaitFor,
False, INFINITE);

它用了 INFINITE 了.就是永远等待,直到有信号
那后面那个 until 的循环是多余的.

作者为什么要这样写.我不得而知

我想是不是作者本来不想用 INFINITE ,而是指定一个等待的毫秒.如 200 ms .

这时这个循环是有用的.因为 200ms 后,数据可能还没写完.只传递了一部份.

猜想
 
如果是你说的情况,等待超时,那样的话后台仍然在执行中
GetOverlappedResult(hCommFile,
lpOverlappedWrite^,
dwNumberOfBytesWritten,
True)//这个True会等到执行完毕才返回.
如果将这个True换成False的话,虽然立即返回但后台(系统)还是在继续执行进程的Overlapped请求.
这样子的话,线程又一次请求系统将pDataToWrite[ dwWhereToStartWriting ]所指向的内存写入文件中.
两次请求中第一次需要写的内存包含了第二次的内存.这个不是重复操作了么?
这样子不就是逻辑错了么?
是我理解的不对还是SPComm控件本身的逻辑错误?
 
SPCOMM 本身没有什么错误.可能代码上有点罗嗦
 
多人接受答案了。
 
后退
顶部