Multithreading 带CPort的线程

Multithreading 带CPort的线程,multithreading,delphi,port,pascal,Multithreading,Delphi,Port,Pascal,我正在尝试用delphi编写一个简单的应用程序 我希望它监听一个端口,在收到消息后,它将等待4秒钟,然后发送一个字符串作为响应 unit Tests.Mocks.Refractometer; interface uses CPort, Classes ; type TRefractometerMock = class strict private MockRunThread : TThread; ComPort : TComPort;

我正在尝试用delphi编写一个简单的应用程序

我希望它监听一个端口,在收到消息后,它将等待4秒钟,然后发送一个字符串作为响应

unit Tests.Mocks.Refractometer;

interface

uses
  CPort,
  Classes
  ;

type
  TRefractometerMock = class
    strict private
      MockRunThread : TThread;
      ComPort : TComPort;
      ComDataPacket: TComDataPacket;
    public
      procedure Open;
      procedure HandlePacket(Sender : TObject; const Str : String);

      constructor Create; overload;
      constructor Create(BaudRate : TBaudRate; Port : String); overload;
      destructor Destroy; override;
  end;

implementation

uses
  SysUtils,
  StrUtils
  ;

procedure TRefractometerMock.HandlePacket(Sender : TObject; const Str : String);
begin
    MockRunThread.Start;    
end;

procedure TRefractometerMock.Open;
begin
    ComPort.Open;
end;

constructor TRefractometerMock.Create(BaudRate : TBaudRate; Port : String);
begin
    Self.Create;
    Self.ComPort.Port := Port;
    Self.ComPort.BaudRate := BaudRate;
end;

constructor TRefractometerMock.Create;
begin
    inherited;
    ComPort := TComPort.Create(nil);
    ComDataPacket := TComDataPacket.Create(nil);

    ComDataPacket.ComPort := ComPort;
    ComDataPacket.OnPacket := HandlePacket;

    MockRunThread := TThread.CreateAnonymousThread
    (
        procedure
        begin
            Sleep(4000);
            Self.ComPort.WriteStr('nD=1.33308;');
        end
    );
end;

destructor TRefractometerMock.Destroy;
begin
    if Assigned(Self.ComPort)  then FreeAndNil(Self.ComPort);
    if Assigned(ComDataPacket) then FreeAndNil(ComDataPacket);
    if Assigned(MockRunThread) then FreeAndNil(MockRunThread);

    inherited;
end;

end.

使用此单元,我可以使用以下代码

开始听

RefractometerMock := TRefractometerMock.Create(TBaudRate.br9600, 'COM7');
try
    RefractometerMock.Open;

    Sleep(8000);

finally
    FreeAndNil(RefractometerMock);
end;
还要注意,我正在使用创建端口
COM6
COM7
之间的网桥

我正在端口
COM6上发送putty消息

问题是,即使我用putty发送了一条消息,
HandlePacket
方法也不会被调用,直到
TRefractometerMock
对象被释放

首先

然后

然后

最后


我甚至不确定这是怎么可能的,因为我认为这个对象已被销毁。

我没有看到ComDataPacket的任何设置。从帮助:
当出现一种停止条件时,数据包结束
。您是否定义了这些停止条件?
您是否在简单的独立应用程序中使用ComDataPacket检查数据接收,而不使用中间类


顺便说一句,TTimer似乎可以完成这项工作,这里不需要线程。

您正在通过
Sleep(8000)
阻塞主线程。这意味着com端口驱动程序无法调用
HandlePacket
方法

当睡眠结束时,处理任何事情都为时已晚,因为一切都被释放了

由于您正在处理匿名线程的生存期,因此应该将
FreeOnTerminate
属性设置为false。并在匿名线程之后释放com端口


使用计时器而不是
Sleep()
调用。

因为Brian Frost想要这里的代码,所以它太大了,无法放入注释中

创建一个简单的表单

type
  TFrmMockRefrac = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    RefractometerMock : TRefractometerMock;
    { Public declarations }
  end;

var
  FrmMockRefrac: TFrmMockRefrac;

在不使用
Sleep
功能的情况下处理创建和销毁

procedure TFrmMockRefrac.FormCreate(Sender: TObject);
begin
    RefractometerMock := TRefractometerMock.Create(TBaudRate.br9600, 'COM7');
    RefractometerMock.Open;
end;

procedure TFrmMockRefrac.FormDestroy(Sender: TObject);
begin
    FreeAndNil(RefractometerMock);
end;

你没有启动线程。匿名线程被创建为挂起。您需要调用MockRunThread.Start@AllenBauer
MockRunThread.Start
HandlePacket
函数中被调用。当从com端口接收到数据包时,应调用此函数。至少,这是我希望发生的。@sav:CPort和TAnonymousThread的组合是一个有用的参考。你能用陆路的mods发布你更正的代码吗?谢谢你给我指向com0com的指针。我真的不知道如何用定时器来实现这一点。也许如果我将此代码添加到表单中,而不是从控制台应用程序调用它