📄 awwin32.pas
字号:
ResetEvent(ReadOL.hEvent);
end;
end;
end;
Result := Integer(Temp);
end;
function TApdWin32Dispatcher.SetComState(var DCB: TDCB): Integer;
{-Set the a new communications device state from DCB}
begin
if SetCommState(CidEx, DCB) then
Result := 0
else
Result := -Integer(GetLastError);
end;
function TApdWin32Dispatcher.WriteCom(Buf: PChar; Size: Integer): Integer;
{-Write data to the comport}
type
PBArray = ^TBArray;
TBArray = array[0..pred(High(Integer))] of Byte;
var
SizeAtEnd : Integer;
LeftOver : Integer;
begin
{Add the data to the output queue}
EnterCriticalSection(OutputSection);
try
{we already know at this point that there is enough room for the block}
SizeAtEnd := OutQue - OBufHead;
if SizeAtEnd >= Size then begin
{can move data to output queue in one block}
Move(Buf^, OBuffer^[OBufHead], Size);
if SizeAtEnd = Size then
OBufHead := 0
else
Inc(OBufHead, Size);
end else begin
{ need to use two moves }
Move(Buf^, OBuffer^[OBufHead], SizeAtEnd);
LeftOver := Size - SizeAtEnd;
Move(PBArray(Buf)^[SizeAtEnd], OBuffer^, LeftOver);
OBufHead := LeftOver;
end;
finally
LeaveCriticalSection(OutputSection);
end;
{...finally, wake up the output thread to send the data}
SetEvent(OutputEvent);
Result := Size; {report all was sent}
end;
function TApdWin32Dispatcher.SetupCom(InSize, OutSize : Integer) : Boolean;
{-Set new in/out buffer sizes}
begin
Result := SetupComm(CidEx, InSize, OutSize);
end;
function TApdWin32Dispatcher.WaitComEvent(var EvtMask : DWORD;
lpOverlapped : POverlapped) : Boolean;
begin
Result := WaitCommEvent(CidEx, EvtMask, lpOverlapped);
end;
procedure TApdWin32Dispatcher.StartDispatcher;
begin
EnterCriticalSection(DataSection);
try
{See if we're already active}
if DispActive then
raise Exception.Create('Dispatcher already started');
DispActive := True;
{Create the com events thread}
KillThreads := False;
ComThread := TComThread.Create(Self);
{Wait for it to start...}
WaitForSingleObject(GeneralEvent, ThreadStartWait);
{$IFDEF DebugThreadConsole}
Writeln(ThreadStatus(ComStart));
{$ENDIF}
{Create the dispatcher thread}
fDispThread := TDispThread.Create(Self);
{Wait for it to start...}
WaitForSingleObject(GeneralEvent, ThreadStartWait);
{$IFDEF DebugThreadConsole}
Writeln(ThreadStatus(DispStart));
{$ENDIF}
{Create the output thread}
OutThread := TOutThread.Create(Self);
{Wait for it to start...}
WaitForSingleObject(GeneralEvent, ThreadStartWait);
{$IFDEF DebugThreadConsole}
Writeln(ThreadStatus(OutStart));
{$ENDIF}
finally
LeaveCriticalSection(DataSection);
end;
end;
procedure TApdWin32Dispatcher.StopDispatcher;
var
ET : EventTimer;
begin
EnterCriticalSection(DataSection);
try
if not DispActive then
Exit;
{ Set the flag to kill the threads next time they wake, or after }
{ their current processing }
KillThreads := True;
if Assigned(OutThread) then begin
{Force the output thread to wake...}
SetEvent(OutFlushEvent);
{...and wait for it to die}
while (OutThread <> nil) do
SafeYield;
{$IFDEF DebugThreadConsole}
Writeln(ThreadStatus(OutKill));
{$ENDIF}
end;
if Assigned(ComThread) then begin
{Force the comm thread to wake...}
SetCommMask(CidEx, 0);
SetEvent(ReadyEvent);
{... and wait for it to die}
ResetEvent(GeneralEvent);
while (ComThread <> nil) do
SafeYield;
{$IFDEF DebugThreadConsole}
Writeln(ThreadStatus(ComKill));
{$ENDIF}
end;
{Now kill the timer}
KillTimer(0, TimerID);
if Assigned(DispThread) then begin
KillThreads := True;
{Wait for it to die}
NewTimer(ET, 36); { start a 2-second timer to prevent blocks }
while (DispThread <> nil) and not(TimerExpired(ET)) do
SafeYield;
if DispThread <> nil then begin
{$IFDEF DebugThreadConsole}
WriteLn('DispThread<>nil');
{$ENDIF}
{ thread didn't die, reset the event }
SetEvent(ComEvent);
{Wait for it to die yet again}
NewTimer(ET, 36); { start a 2-second timer to prevent blocks }
while (DispThread <> nil) and not(TimerExpired(ET)) do
SafeYield;
if DispThread <> nil then
{ disp thread is not responding, brutally terminate it }
DispThread.Free;
end;
{$IFDEF DebugThreadConsole}
Writeln(ThreadStatus(DispKill));
{$ENDIF}
end;
if ComEvent <> INVALID_HANDLE_VALUE then begin
if CloseHandle(ComEvent) then
ComEvent := INVALID_HANDLE_VALUE;
end;
if ReadyEvent <> INVALID_HANDLE_VALUE then begin
if CloseHandle(ReadyEvent) then
ReadyEvent := INVALID_HANDLE_VALUE;
end;
if GeneralEvent <> INVALID_HANDLE_VALUE then begin
if CloseHandle(GeneralEvent) then
GeneralEvent := INVALID_HANDLE_VALUE;
end;
if OutputEvent <> INVALID_HANDLE_VALUE then begin
if CloseHandle(OutputEvent) then
OutputEvent := INVALID_HANDLE_VALUE;
end;
if SentEvent <> INVALID_HANDLE_VALUE then begin
if CloseHandle(SentEvent) then
SentEvent := INVALID_HANDLE_VALUE;
end;
if OutFlushEvent <> INVALID_HANDLE_VALUE then begin
if CloseHandle(OutFlushEvent) then
OutFlushEvent := INVALID_HANDLE_VALUE;
end;
finally
LeaveCriticalSection(DataSection);
end;
end;
function TApdWin32Dispatcher.ProcessCommunications : Integer;
{-Communications are running in separate threads -- give them a chance}
begin
Sleep(0);
Result := 0;
end;
constructor TApdTAPI32Dispatcher.Create(Owner : TObject; InCid : Integer);
begin
CidEx := InCid;
inherited Create(Owner);
end;
function TApdTAPI32Dispatcher.OpenCom(ComName: PChar; InQueue, OutQueue : Cardinal) : Integer;
begin
ReadOL.hEvent := CreateEvent(nil, True, False, nil);
WriteOL.hEvent := CreateEvent(nil, True, False, nil);
if (ReadOL.hEvent = 0) or (WriteOL.hEvent = 0) then begin
CloseCom;
Result := -1;
Exit;
end;
if CidEx <> 0 then
Result := CidEx
else begin
Result := ecCommNotOpen;
SetLastError(-Result);
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -