刚接触几天delphi,写了一个多线程处理串口的小程序可是运行一会会报错,希望大家看下哪里的问题,一个线程负责读数据,一个线程显示,主线程负责一少部分的控制
错误信息:不合法的指针unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, CPortCtl, StdCtrls, CPort, iScope, iComponent, iVCLComponent,
  iCustomComponent, iPlotComponent, iPlot, ExtCtrls,Contnrs,Unit2,Unit3;type
  TForm1 = class(TForm)
    ComPort1: TComPort;
    GroupBox1: TGroupBox;
    Button1: TButton;
    RadioButton1: TRadioButton;
    Edit1: TEdit;
    ComLed1: TComLed;
    ComLed2: TComLed;
    Memo1: TMemo;
    function strtohexstr(const S:string ): string ;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form1: TForm1;
  Dataqueue :TQueue;
  readthread :TSerialThread;
  paintthread :TPaintThread;implementation{$R *.dfm}
function TForm1.strtohexstr(const S:string):string;
var I:Integer;
begin
  for I:=1 to Length(S) do
  begin
      if I=1 then
      Result:=IntToHex(Ord(S[1]),2)
    else Result:=Result+' '+IntToHex(Ord(S[I]),2);
    end;
end;procedure TForm1.Button1Click(Sender: TObject);
begin    if  Button1.caption = '打开串口' then
    begin       Comport1.ShowSetupDialog;
       if  radiobutton1.Checked then
         comport1.CustomBaudRate := 1000000;
       comport1.Open;
       readthread.Resume;
       paintthread.Resume;
       Button1.caption := '关闭串口';
    end
    else if Button1.caption = '关闭串口' then
        begin
           readthread.Suspend;
           paintthread.Suspend;
           comport1.Close;
           Button1.caption := '打开串口';
        end;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
  Dataqueue := TQueue.Create;
  readthread := TSerialThread.Create(@Comport1,@Dataqueue);
  paintthread := TPaintThread.Create(@Dataqueue,@memo1);
  
end;end.unit Unit2;interfaceuses
  Classes,Contnrs,CPortCtl,CPort;type
  TpointertoTqueue = ^TQueue;
  TpointCport = ^TComPort;
  TSerialThread = class(TThread)
  private
    { Private declarations }
     PQueue :TpointertoTqueue;
     PPort  : TpointCport;
  protected
    procedure Execute; override;
    procedure read;
  public
    constructor Create(port:TpointCport;p:TpointertoTqueue);
  end;
implementationprocedure TSerialThread.Execute;
begin
  { Place thread code here }
  while true do
  begin
    read;
  end;
end;
procedure TSerialThread.read;
var count:integer;
    buf :array[1..65535] of Byte;
    i : integer;
    pbyte :^byte;
begin
    if PPort^.Connected then
    begin
      count := PPort^.InputCount;
      if count > 0 then
       begin
          PPort^.Read(buf,count);
          for i:=1 to count do
          begin
              New(pbyte);
              pbyte^ :=buf[i];
              PQueue^.Push(pbyte);
          end;
       end;
    end;
end;
constructor TSerialThread.Create(port:TpointCport;p:TpointertoTqueue);
begin
  PPort := port;
  PQueue := p;
  inherited Create(true);
end;
end.
 
unit Unit3;interfaceuses
  Classes,StdCtrls,Contnrs,CPortCtl,CPort,SysUtils;type
  TpointertoTqueue = ^TQueue;
  TpointerTmemo = ^TMemo;
  TPaintThread = class(TThread)
  private
    { Private declarations }
    pqueue :TpointertoTqueue;
    pmemo  :TpointerTmemo;
  protected
    procedure Execute; override;
    procedure paint;
  public
    constructor Create(p1:TpointertoTqueue;p2:TpointerTmemo);
  end;implementation{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,      Synchronize(UpdateCaption);  and UpdateCaption could look like,    procedure TPaintThread.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }{ TPaintThread }procedure TPaintThread.Execute;
begin
  { Place thread code here }
  while true do
  begin
   paint;
  end;
end;constructor TPaintThread.Create(p1:TpointertoTqueue;p2:TpointerTmemo);
begin
  pqueue := p1;
  pmemo := p2;
  inherited Create(true);
end;procedure TPaintThread.paint;
var i:integer;
    temp:^Byte;
begin
    if pqueue^.Count >100 then
    begin
       for i:=1 to 100 do
       begin
          temp := pqueue^.Pop;
          pmemo^.Lines.Add(IntToHex(temp^,2));
          dispose(temp);
         // if pmemo^.Lines.Count > 500 then
         // pmemo^.Lines.Clear;
       end;
    end;end;
end.
 

解决方案 »

  1.   

    procedure TPaintThread.paint;
    var i:integer;
        temp:^Byte;
    begin
        if pqueue^.Count >100 then
        begin
           for i:=1 to 100 do
           begin
              temp := pqueue^.Pop;
              pmemo^.Lines.Add(IntToHex(temp^,2));
              dispose(temp);
             // if pmemo^.Lines.Count > 500 then
             // pmemo^.Lines.Clear;
           end;
        end;end;
    end.
     
    -----------------------------
    你这不是在操作VCL吗?当然很容易出错,大概几秒就出错啊
      

  2.   

    是在操作vcl,出错的原因是什么的?能不能再解释下啊
      

  3.   

    { Important: Methods and properties of objects in visual components can only be
      used in a method called using Synchronize, for example,      Synchronize(UpdateCaption);  and UpdateCaption could look like,    procedure TPaintThread.UpdateCaption;
        begin
          Form1.Caption := 'Updated in a thread';
        end; }
    这个就是解释.