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

📄 awwin32.pas

📁 Async Professional 4.04
💻 PAS
📖 第 1 页 / 共 2 页
字号:
          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 + -